WebView的一些坑
loadData()方法
我们可以通过使用WebView.loadData(String data, String mimeType, String encoding)
方法来加载一整个 HTML 页面的一小段内容,第一个就是我们需要WebView展示的内容,第二个是我们告诉 WebView我们展示内容的类型,第三个是字节码,但是使用的时候,这里会有一些坑。
String html = new String("<h3>我是loadData() 的标题</h3><p>  我是他的内容</p>");
webView.loadData(html, "text/html", "UTF-8");
解决方案
String html = new String("<h3>我是loadData() 的标题</h3><p>  我是他的内容</p>");
webView.loadData(html, "text/html;charset=UTF-8", "null");
我们的 Data 数据里不能出现’#’、‘%’、‘\’、‘?’这四个字符,如果出现了我们要用 %23, %25, %27, %3f 对应来替代,网上列举了未将特定字符转义过程中遇到的异常现象:
- % 会报找不到页面错误,页面全是乱码。
- # 会让你的 goBack 失效,但 canGoBAck 是可以使用的,于是就会产生返回按钮生效,但不能返回的情况。
- \ 和 ? 在转换时,会报错,因为它会把 \ 当作转义符来使用,如果用两级转义,也不生效。
补充阅读
在写WebView时,感觉LoadUrl太浪费流量,而且加载起来有点慢,就考虑用其它的方法来实现。在加载页面时,如果只加载数据,页面模板提前写好放到项目中,这样就可以来更快的加载页面,用户体验会好些。
可以采用onLoadData()
和onLoadDataWithBaseURL()
了。据说后者比前者速度快1~2倍。
页面空白
当 WebView 嵌套在 ScrollView 里面的时候,如果 WebView 先加载了一个高度很高的网页,然后加载了一个高度很低的网页,就会造成 WebView 的高度无法自适应,底部出现大量空白的情况出现。
Google 建议不要在 ScrollView 中使用 WebView。
解决方案
移除重新添加新的 WebView
每次加载新的url的时候remove掉旧的WebView,重新加入一个新的 WebView去加载这个新的url。
缺点:效率不高
重新设置高度
JS注入,获取页面内容高度,设置成WebView高度。
(function(w){
window.App.resize(document.body.getBoundingClientRect().height);
})(window);
@JavascriptInterface
public void resize(final float height) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//Toast.makeText(getActivity(), height + "", Toast.LENGTH_LONG).show();
//此处的 layoutParmas 需要根据父控件类型进行区分,这里为了简单就不这么做了
mWebView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density)));
}
});
}
加载一个空网页
在从高网页加载低网页的时候,先加载一个空内容,接着立马做相关的处理操作。
// load empty data to shrink the WebView instance
mArticleWebView.loadUrl("");
// load real data
mArticleWebView.loadDataWithBaseURL(null,data,"text/html","utf-8",null);
内存泄漏
内存暴涨
但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用webview.destroy();webview=null;对内存占回收用还是没有任何效果
解决方案:
- 为加载WebView的界面开启新进程,在该页面退出之后关闭这个进程
- 不要在xml中定义webview节点,而是在需要的时候动态生成
setBuiltInZoomControls引起的Crash
当使用mWebView.getSettings().setBuiltInZoomControls(true) 启用该设置后,用户一旦触摸屏幕,就会出现缩放控制图标。这个图标过上几秒会自动消失,但在3.0 之上 4.4 系统之下很多手机会出现这种情况:
如果图标自动消失前退出当前 Activity 的话,就会发生 ZoomButton 找不到依附的 Window 而造成程序崩溃。
解决办法很简单就是在 Activity 的 onDestory 方法中调用 mWebView.setVisibility(View.GONE); 方法,手动将其隐藏,就不会崩溃了。
后台无法释放JS导致耗电
如果 WebView 加载的的 html 里有一些 JS 一直在执行比如动画之类的东西,如果此刻 WebView 挂在了后台,这些资源是不会被释放,用户也无法感知,导致一直占有 CPU 增加耗电量。
解决方案,在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可。