WebView的一些坑

loadData()方法

我们可以通过使用WebView.loadData(String data, String mimeType, String encoding)方法来加载一整个 HTML 页面的一小段内容,第一个就是我们需要WebView展示的内容,第二个是我们告诉 WebView我们展示内容的类型,第三个是字节码,但是使用的时候,这里会有一些坑。

String html = new String("<h3>我是loadData() 的标题</h3><p>&nbsp&nbsp我是他的内容</p>");
webView.loadData(html, "text/html", "UTF-8");

解决方案

String html = new String("<h3>我是loadData() 的标题</h3><p>&nbsp&nbsp我是他的内容</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;对内存占回收用还是没有任何效果

解决方案:

  1. 为加载WebView的界面开启新进程,在该页面退出之后关闭这个进程
  2. 不要在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 即可。

results matching ""

    No results matching ""