android webview常见问题,android webview常见问题以及性能优化

1.webview导致内存泄露问题

使用 WebView 的时候,不在 XML 里面声明,而是在代码中直接 new 出来,传入 application context 来防止 activity 引用被滥用

WebView webView = new WebView(getContext().getApplicationContext());

webFrameLayout.addView(webView,0);

在activity的ondestory的时候需要做一下操作

if (mWebView != null) {

mWebView.stopLoading();//再次打开页面时,若界面没有消亡,会导致进度条不显示并且界面崩溃

mWebView.onPause();

mWebView.clearCache(true)

mWebView.clearHistory();

mWebView.removeAllViews();

mWebView.destroyDrawingCache();

ViewGroup parent = (ViewGroup) mWebView.getParent();

if (parent != null) {

parent.removeView(mWebView);

}

mWebView.removeAllViews();

mWebView.destroy();//这句由于有些在其他线程还没有结束,会导致空指针异常导致没办法使用

mWebView = null;

}

这里面有个需要特别注意的地方就是如果你在调用webview.destory();的时候,如果webview里面还有别的线程在操作,就会导致当前这个webview为空。这时候我们需要结束相应线程。例如我们项目中有一个广告拦截是通过在

public void onPageFinished(final WebView view, String url)

里面启用一个runnable去执行一串的js脚本,如果用户在你脚本没执行完成的时候就关闭了当前界面,系统就会抛出空指针异常。这时候就需要通过去onPageFinished获取webview对象,封装成以下方法

public void stopJsLoad(){

if (mWebView != null) {

mWebView.removeCallbacks(runnable);

runnable = null;

}

}

然后在activity的onDestory()方法里面调用

if (mWebViewClient != null) {

mWebViewClient.stopJsLoad();

mWebViewClient = null;

}

2.WebView页面中播放了音频,退出Activity后音频仍然在播放,需要在Activity的onDestory()中调用

ViewGroup parent = (ViewGroup) mWebView.getParent();

if (parent != null) {

parent.removeView(mWebView);

}

mWebView.removeAllViews();

mWebView.destroy();

mWebView = null;

3.webview加载一些别人的url时候,有时候会发生证书认证错误的情况,这时候我们希望能够正常的呈现页面给用户,我们需要忽略证书错误,需要调用WebViewClient类的onReceivedSslError方法,调用handler.proceed()来忽略该证书错误。

4.webview支持H5通过浏览器远程调试配置

if (BuildConfig.DEBUG){

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){

webview.setWebContentsDebuggingEnabled(true);

}

}

5.webview先加载样式之后再加载图片配置

/*

* 默认情况html代码下载到WebView后,webkit开始解析网页各个节点,

* 发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件

* ,但如果在这之前也有解析到image节点,那势必也会发起网络请求下载相应的图片

* 。在网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到css或js文件加载完成的时间

* ,造成页面空白loading过久。解决的方法就是告诉WebView先不要自动加载图片,等页面finish后再发起图片加载。

* 在系统API在19以上的版本作了兼容

* 因为4.4以上系统在onPageFinished时再恢复图片加载时,如果存在多张图片引用的是相同的src时,

* 会只有一个image标签得到加载,因而对于这样的系统我们就先直接加载。 */

if (Build.VERSION.SDK_INT >= 19) {

// settings.setLoadsImagesAutomatically(true); // 图片下载阻塞

settings.setBlockNetworkImage(true);

} else {

settings.setLoadsImagesAutomatically(false);

}

6.H5页面有混合http和https的链接,5.0以上系统不支持混合模式,需要通过配置来开启

//5.0及以上webview不支持http和https混合模式 需要通过配置来开启混合模式if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

}

7.webview 拦截网页请求方法

public WebResourceResponse shouldInterceptRequest(WebView webView, String url) 从 API 11 引入,API 21 废弃

public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) 从 API 21 开始引入

@Override

public WebResourceResponse shouldInterceptRequest(WebView webView, final String url) {

WebResourceResponse response = null;

boolean resDown = JSHelper.isURLDownValid(url);

if (resDown) {

jsStr = JsjjJSHelper.getResInputStream(url);

if (url.endsWith(".png")) {

response = getWebResourceResponse(url, "image/png", ".png");

} else if (url.endsWith(".gif")) {

response = getWebResourceResponse(url, "image/gif", ".gif");

} else if (url.endsWith(".jpg")) {

response = getWebResourceResponse(url, "image/jepg", ".jpg");

} else if (url.endsWith(".jepg")) {

response = getWebResourceResponse(url, "image/jepg", ".jepg");

} else if (url.endsWith(".js") && jsStr != null) {

response = getWebResourceResponse("text/javascript", "UTF-8", ".js");

} else if (url.endsWith(".css") && jsStr != null) {

response = getWebResourceResponse("text/css", "UTF-8", ".css");

} else if (url.endsWith(".html") && jsStr != null) {

response = getWebResourceResponse("text/html", "UTF-8", ".html");

}

}

return response;

}

});

private WebResourceResponse getWebResourceResponse(String url, String mime, String style) {

WebResourceResponse response = null;

try {

response = new WebResourceResponse(mime, "UTF-8", new FileInputStream(new File(getJSPath() + TPMD5.md5String(url) + style)));

} catch (FileNotFoundException e) {

e.printStackTrace();

}

return response;

}

public String getJsjjJSPath() {

String splashTargetPath = JarEnv.sApplicationContext.getFilesDir().getPath() + "/JS";

if (!TPFileSysUtil.isDirFileExist(splashTargetPath)) {

TPFileSysUtil.createDir(splashTargetPath);

}

return splashTargetPath + "/";

}

8.通过获取Web页中的title用来设置自己界面中的title及相关问题

WebChromeClient webChromeClient = new WebChromeClient() {

@Override

public void onReceivedTitle(WebView view, String title) {

super.onReceivedTitle(view, title);

txtTitle.setText(title);

}

};

在有些手机上当通过webview.goBack()回退的时候,并没有触发onReceiveTitle(),这样会导致标题仍然是之前子页面的标题,没有切换回来.

(1) 可以确定webview中子页面只有二级页面,没有更深的层次,这里只需要判断当前页面是否为初始的主页面,可以goBack的话,只要将标题设置回来即可.

(2)webview中可能有多级页面或者以后可能增加多级页面,这种情况处理起来要复杂一些:

因为正常顺序加载的情况onReceiveTitle是一定会触发的,所以就需要自己来维护webview loading的一个url栈及url与title的映射关系

那么就需要一个ArrayList来保持加载过的url,一个HashMap保存url及对应的title.

正常顺序加载时,将url和对应的title保存起来,webview回退时,移除当前url并取出将要回退到的web 页的url,找到对应的title进行设置即可.

(3)当加载出错的时候,比如无网络,这时onReceiveTitle中获取的标题为 找不到该网页,因此建议当触发onReceiveError时,不要使用获取到的title.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值