Android MVVM框架搭建腾讯X5WebView + DrawerLayout + NavigationView
Posted 初学者-Study
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MVVM框架搭建腾讯X5WebView + DrawerLayout + NavigationView相关的知识,希望对你有一定的参考价值。
android MVVM框架搭建(六)腾讯X5WebView + DrawerLayout + NavigationView
前言
在上一篇文章中在HomeActivity中通过装载不同的Fragment显示不同的数据,目前有新闻数据和视频数据,不过光是显示数据,看不到详细内容也不行。其次在这样的页面中要想显示个人信息的话,可以增加一个Fragment或者通过侧滑抽屉来显示,同时既然有个人信息页面,自然就要有登录和注册的关系,之前的登录是个假的,这次我就做的真一点,用一下本地数据库。
效果图
正文
首先我们先显示新闻详情信息。这里会用到WebView,Android原生的WebView好不好用,用过的就不会再用,因此我们用更加好用的WebView,就是腾讯的X5 WebView,你可以看到微信里面也是这个WebView。要使用这个WebView需要添加依赖。
一、添加依赖
在app的build.gradle中的dependencies闭包中添加如下代码:
// 腾讯X5内核WebView
implementation 'com.tencent.tbs:tbssdk:44085'
添加后,点击Sync Now,进行项目同步。
二、使用WebView
下面在Activity中新建一个WebActivity,布局是activity_web.xml,这个类用于装载WebView显示,首先改一下布局activity_web.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ui.activity.WebActivity">
<com.tencent.smtt.sdk.WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
然后在WebActivity中增加如下代码,用于配置WebView。
private final WebViewClient client = new WebViewClient()
/**
* 防止加载网页时调起系统浏览器
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
view.loadUrl(url);
return true;
@Override
public void onReceivedHttpAuthRequest(WebView webview,
com.tencent.smtt.export.external.interfaces.HttpAuthHandler httpAuthHandlerhost, String host,
String realm)
boolean flag = httpAuthHandlerhost.useHttpAuthUsernamePassword();
@Override
public void onPageFinished(WebView webView, String s)
super.onPageFinished(webView, s);
@Override
public void onReceivedError(WebView webView, int i, String s, String s1)
System.out.println("***********onReceivedError ************");
super.onReceivedError(webView, i, s, s1);
@Override
public void onReceivedHttpError(WebView webView, WebResourceRequest webResourceRequest, WebResourceResponse webResourceResponse)
System.out.println("***********onReceivedHttpError ************");
super.onReceivedHttpError(webView, webResourceRequest, webResourceResponse);
;
当前的页面是需要网络请求的,因此就会有相应的ViewModel和Repository,因为聚合给的新闻数据里面有一个uniquekey,用于查询新闻的详情信息,然后再去返回的详情信息里面找到url通过WebView去加载。当然并不是每一条新闻都能够去显示的,有一些新闻是没有详情信息的,这在我们点击新闻的时候就要做处理。
这是我们下面要做的事情,现在对于X5WebView还需要进行一个初始化,这样做是方便使用的。在BaseApplication中增加如下代码:
private void initX5WebView()
HashMap map = new HashMap(2);
map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true);
map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true);
QbSdk.initTbsSettings(map);
//搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback()
@Override
public void onViewInitFinished(boolean arg0)
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
Log.d("app", " onViewInitFinished is " + arg0);
@Override
public void onCoreInitFinished()
;
//x5内核初始化接口
QbSdk.initX5Environment(getApplicationContext(), cb);
然后在onCreate中调用它。
下面关于WebView的使用就只有一步了,那就是加载url,现在还没有的,去获取它。
三、获取新闻详情
在聚合API中获取新闻详情是另一个接口,在写这个接口之前,先写一个返回的新闻详情数据。
① 新闻详情数据
在model包下新增一个NewsDetailResponse类,里面的代码如下:
public class NewsDetailResponse
private String reason;
private ResultBean result;
private Integer error_code;
public String getReason()
return reason;
public void setReason(String reason)
this.reason = reason;
public ResultBean getResult()
return result;
public void setResult(ResultBean result)
this.result = result;
public Integer getError_code()
return error_code;
public void setError_code(Integer error_code)
this.error_code = error_code;
public static class ResultBean
private String uniquekey;
private DetailBean detail;
private String content;
public String getUniquekey()
return uniquekey;
public void setUniquekey(String uniquekey)
this.uniquekey = uniquekey;
public DetailBean getDetail()
return detail;
public void setDetail(DetailBean detail)
this.detail = detail;
public String getContent()
return content;
public void setContent(String content)
this.content = content;
public static class DetailBean
private String title;
private String date;
private String category;
private String author_name;
private String url;
private String thumbnail_pic_s;
private String thumbnail_pic_s02;
private String thumbnail_pic_s03;
public String getTitle()
return title;
public void setTitle(String title)
this.title = title;
public String getDate()
return date;
public void setDate(String date)
this.date = date;
public String getCategory()
return category;
public void setCategory(String category)
this.category = category;
public String getAuthor_name()
return author_name;
public void setAuthor_name(String author_name)
this.author_name = author_name;
public String getUrl()
return url;
public void setUrl(String url)
this.url = url;
public String getThumbnail_pic_s()
return thumbnail_pic_s;
public void setThumbnail_pic_s(String thumbnail_pic_s)
this.thumbnail_pic_s = thumbnail_pic_s;
public String getThumbnail_pic_s02()
return thumbnail_pic_s02;
public void setThumbnail_pic_s02(String thumbnail_pic_s02)
this.thumbnail_pic_s02 = thumbnail_pic_s02;
public String getThumbnail_pic_s03()
return thumbnail_pic_s03;
public void setThumbnail_pic_s03(String thumbnail_pic_s03)
this.thumbnail_pic_s03 = thumbnail_pic_s03;
② 新闻详情数据API
/**
* 聚合新闻数据详情
*/
@GET("/toutiao/content?key=99d3951ed32af2930afd9b38293a08a2")
Observable<NewsDetailResponse> newsDetail(@Query("uniquekey") String uniquekey);
这个接口用于请求新闻详情数据,返回值将会解析成NewsDetailResponse。
③ WebRepository
数据有了,API接口有了,下面就是去调用的地方了,在repository包下新增一个WebRepository类,里面的代码如下:
@SuppressLint("CheckResult")
public class WebRepository
final MutableLiveData<NewsDetailResponse> newsDetail = new MutableLiveData<>();
public final MutableLiveData<String> failed = new MutableLiveData<>();
/**
* 获取新闻详情数据
* @param uniquekey 新闻ID
* @return newsDetail
*/
public MutableLiveData<NewsDetailResponse> getNewsDetail(String uniquekey)
NetworkApi.createService(ApiService.class, 2).
newsDetail(uniquekey).compose(NetworkApi.applySchedulers(new BaseObserver<NewsDetailResponse>()
@Override
public void onSuccess(NewsDetailResponse newsDetailResponse)
if (newsDetailResponse.getError_code() == 0)
newsDetail.setValue(newsDetailResponse);
else
failed.postValue(newsDetailResponse.getReason());
@Override
public void onFailure(Throwable e)
failed.postValue("NewsDetail Error: " + e.toString());
));
return newsDetail;
很简单的代码,和之前的地方基本上没啥差别。
④ WebViewModel
数据获取有了,下面就是通过ViewModel去关联Activity。在viewmodels包下新建一个WebViewModel,里面的代码如下:
public class WebViewModel extends BaseViewModel
public LiveData<NewsDetailResponse> newsDetail;
public void getNewDetail(String uniquekey)
WebRepository webRepository = new WebRepository();
failed = webRepository.failed;
newsDetail = webRepository.getNewsDetail(uniquekey);
下面就是在WebActivity中去观察这个网络返回的数据了。
⑤ 页面数据处理
打开WebActivity,实际上我们只需要修改onCreate中的代码就可以了,代码如下:
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
ActivityWebBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_web);
WebViewModel viewModel = new ViewModelProvider(this).get(WebViewModel.class);
binding.webView.setWebViewClient(client);
setStatusBar(true);
// 在调用TBS初始化、创建WebView之前进行如下配置
String uniquekey = getIntent().getStringExtra("uniquekey");
if (uniquekey != null)
viewModel.getNewDetail(uniquekey);
viewModel.newsDetail.observe(context, newsDetailResponse ->
binding.webView.loadUrl(newsDetailResponse.getResult().getDetail().getUrl()));
viewModel.failed.observe(context, this::showMsg);
这里的代码很常规,首先是绑定布局,然后是ViewModel,再设置webView的配置客户端,设置状态栏,然后就是获取其他页面传递过来的参数,通过这个参数去请求接口,观察返回值,最后加载返回的url。
这里都完成了,下一步就是传递这个参数了,什么时候传递呢?当然是点击的时候了。
四、传递新闻参数
在点击新闻列表中的某一项的时候传递参数到WebActivity中,在NewsAdapter类中添加如下代码:
public static class ClickBinding
public void itemClick(NewsResponse.ResultBean.DataBean dataBean, View view)
if("1".equals(dataBean.getIs_content()))
Intent intent = new Intent(view.getContext(), WebActivity.class);
intent.putExtra("uniquekey", dataBean.getUniquekey());
view.getContext().startActivity(intent);
else
Toast.makeText(view.getContext(), "没有详情信息", Toast.LENGTH_SHORT).show();
当Is_content不为1的时候就表示没有详情信息,则提示一下即可。
然后在convert方法中添加一行代码,如下图所示:
最后就是修改item_newx.xml中的代码了,改动如下图所示:
由于我希望WebView可以沉浸式,因此我在AndroidManifest.xml中对这个WebActivity进行了主题设置,代码如下:
<activity
android:name=".ui.activity.WebActivity"
android:theme="@style/SplashTheme" />
下面就可以运行了。
下面就是点击视频item打开视频的播放地址了。
五、热门视频播放
这里首先要修改视频列表适配器中的内容,打开VideoAdapter,在里面增加如下代码:
public static class ClickBinding
public void itemClick(@NotNull VideoResponse.ResultBean resultBean, View view)
if (resultBean.getShare_url() != null)
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(resultBean.getShare_url())));
else
Toast.makeText(view.getContext(), "视频地址为空", Toast.LENGTH_SHORT).show();
然后convert方法中设置进去。
再修改item_video.xml的代码,如下图所示:
Android MVVM框架搭建OKHttp + Retrofit + RxJava
Android MVVM框架搭建OKHttp + Retrofit + RxJava
Android MVVM框架搭建ViewModel + LiveData + DataBinding
Android MVVM框架搭建ViewModel + LiveData + DataBinding