在这家公司做混合开发已经半年了,接触webview也半年了,期间也体验了crosswalk和TBS等三方,但也有各种各样的问题,最终还是选择了原生webview。对于这系列文章也早有心事,好记性不如烂笔头,但发表到网上又怕别人看到,因为自己理解不够误导大家,所以迟迟没有开始,但随着知识点越来越多,慢慢的就真的有东西记不住了,所以就抓紧写了这系列播客,如有错误请批评,如有帮助,不胜荣幸。
一、动态添加删除webview控件
提到webview最先想到内存泄漏的问题,而解决这个问题最常说到的就是动态添加删除。
a)动态添加:将xml文件中的webview控件用LinearLayout代替,在java代码中初始化webview,添加到LinearLayout中,代码如下
xml布局:<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</RelativeLayout>
java代码:
LinearLayout linear = (LinearLayout) findViewById(R.id.linear);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
WebView web = new WebView(getApplicationContext());
web.setLayoutParams(params);
linear.addView(activity_main_web);
这里需要注意两点,一是
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
这句话一定要添加,我前一阵子看一篇文章没有加这一句,如果你适配的web页面是百度这样的,不添加也能呈现,但是有的web页面就是白屏,还有一个就是
WebView web = new WebView(getApplicationContext());
初始化Webview用的Context,最好用getApplicationContext,因为用这个更稳定,但是有时弹出弹窗的时候出现app崩溃,报错dialog找不到窗口,指向的不是一个应用,上网查全是告诉你把onJsAlert()方法中自定义dialog初始化用的context改成活动窗口的,而不是Application的,但你用的是窗口还是不行,甚至都没有走这个方法,那你就要问一下,这个弹窗是用什么做的,是不是select下拉列表做的,webview内部不支持select下拉列表,会用一个dialog代替,有的时候也不会有什么问题,但我遇到一种情况,就是在一个web页面上覆盖另一个页面,在点击select app就会崩溃,如果你也遇到这种情况,就把初始化webview的getApplicationContext()换成Activity.this试一下,原因未知,但如果使用没问题,还是建议getApplicationContext()。
b)动态删除:动态删除就比较简单了,直接copy就好了:
@Override
protected void onPause() {
super.onPause();
if (web != null) {
web.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (web != null) {
web.onResume();
}
}
//退出程序
@Override
protected void onDestroy() {
super.onDestroy();
if (web != null) {
web.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
web.clearHistory();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
if (linear != null) {
linear.removeView(web);
}
web.removeAllViews();
web.destroy();
} else {
web.removeAllViews();
web.destroy();
if (linear != null) {
linear.removeView(web);
}
}
web = null;
}
}
至此webview控件就算摆上了,接下来就是呈现web页面了,好啦,让我们踩下一个大坑。。。
二、加载适配
a)加载:webview加载web页面的方法差不多都知道,就简单写一下:
webView.loadUrl("http://www.google.com");//加载网络web页面
webView.loadUrl("file:///android_asset/XX.html"); //加载本地web页面
没啥好说的,基本都知道,这个不会自动在自己的app中呈现,需要如下操作:
webView.setWebViewClient(new WebViewClient());
可以自定义一个类集成WebViewClient,然后重写其中方法,括号中初始化自定义的类,如果只是呈现,用不到其中过多方法这样写也行,不过也要重 写shouldOverrideUrlLoading(WebView view, String url)方法,返回ture(自己的代码处理)或者false(Webview处理)。
b)适配:这个地方工作就开始多了,要分开讲了:
1)设置web适应屏幕呈现
主要就是两行代码:
WebSettings webSettings = webView.getSettings();//获取WebSetting,这里面有很多适配webview的方法
webSettings.setUseWideViewPort(true); //设置webview推荐使用的窗口
webSettings.setLoadWithOverviewMode(true);//设置加载模式自适应
也有别的类似功能的方法,webSettings.setLayoutAlgorithm(NARROW_COLUMNS / NORMAL / SINGLE_COLUMN),后来发现弊病很多,就改成这两个了。
2)控制图片加载
按照以上方法做出来,web页面加载出来有时还会乱,这时候我们就可以加上如下方法
//控制图片加载,防止白屏时间过长
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webSettings.setLoadsImagesAutomatically(true);
} else {
webSettings.setLoadsImagesAutomatically(false);
}
3)硬件辅助
其实做完这些工作页面大体可以了,但有时还会有个别错位,这时候就可以在清单配置文件开启硬件加速,还可以顺便在这里增加内存申请量(android并不支持增加内存申请量,只有像我这样小菜才会很少考虑的增加),操作如下:
<application
android:hardwareAccelerated="true"//开启硬件加速
android:largeHeap="true"//增加内存申请量
> </application>
硬件加速可以优化适配,提升速度,但也不是没有坏处,据说会让自定义view变花,总之,如果没有缺点,就不会必须手动开了,在这里我们也简单管理一下:
//防止因开启硬件加速造成的屏幕闪烁
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
4)其它方法
有人说webview是最难控件,我觉得也差不多,他的坑数不胜数,各种方法,很难全部掌握,再简单举几个方法,记录一下(版本控制设置):
//设置保存密码
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
webSettings.setSavePassword(true);
}
//是否允许url加载的JavaScript访问其他的源,包括文件和其他http或https
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
webSettings.setAllowUniversalAccessFromFileURLs(true);
}
//使用DevTools对原生Android应用程序的Android WebViews内容进行调试
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
//还有控制webview的ScrollBar显示的方法
webView.setHorizontalScrollBarEnabled(false);
webView.setVerticalScrollBarEnabled(false);
差不多这些方法一怼,web页面就呈现的差不多了。我在开始这份工作的时候,网上对于webview的讲解少之又少,那时候解决个问题真的是很累,最近倒是出了几篇讲的比较全的博文,但是我感觉和这个系列侧重点不同,那些作者能力很强,注重方法讲解,我则是讲一个混合项目一点点的做出来,完善,如有瑕疵,敬请赐教,如有帮助,不胜荣幸