[Android开发] WebView遇到的问题以及解决
2016-09-05 17:46
721 查看
一、内存泄漏
WebView内存不能回收导致内存溢出,可能很多朋友都试过,说说两种解决方法1. 新开进程
另外单独开一个进程 去使用webview 并且当这个进程结束时,手动调用System.exit(0)这是目前对于webview 内存泄露 最好的解决方案。使用此方法 所有因为webview引发的 资源无法释放等问题 全部可以解决。但是有一个小问题,就是打开时候会慢一点点。
例如一个文章浏览的activity ArticleActivity,在manifest里面添加属性:
<activity android:name=".ArticleActivity" android:process=":school.process.article" android:launchMode="singleTop" android:screenOrientation="portrait"> <intent-filter> <action android:name="school.process.articleactivity" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
同一个应用程序的Activity组件都是运行在同一个进程中,但是,如果Activity配置了android:process这个属性,那么,它就会运行在自己的进程中。如果android:process属性的值以”:”开头,则表示这个进程是私有的;如果android:process属性的值以小写字母开头,则表示这是一个全局进程,允许其它应用程序组件也在这个进程中运行。
因此,这里我们以”:”开头,表示创建的是私有的进程。事实上,这里我们不要前面的”:”也是可以的,但是必须保证这个属性性字符串内至少有一个”.”字符。
在这个页面onDestory的时候,调用一下System.exit(0); 就是退出这个进程。
@Override protected void onDestroy() { if (null != webView) { webView.removeAllViews(); webView.destroy(); } super.onDestroy(); System.exit(0); }
2.调用releaseWebViewCallback
在webview的 onDestroy方法里 调用下面这个方法,很大程度上可以避免内存泄漏public void releaseWebViewCallback() { if (android.os.Build.VERSION.SDK_INT < 16) { try { Field field = WebView.class.getDeclaredField("mWebViewCore"); field = field.getType().getDeclaredField("mBrowserFrame"); field = field.getType().getDeclaredField("sConfigCallback"); field.setAccessible(true); field.set(null, null); } catch (Exception e) { e.printStackTrace(); } } else { try { Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback"); if (sConfigCallback != null) { sConfigCallback.setAccessible(true); sConfigCallback.set(null, null); } } catch (Exception e) { e.printStackTrace(); } } }
二、js调用java的方法,这个方法再调用js 失效的问题
看代码,下面是html代码,在加载的时候调用java代码的showcontacts()这个方法,<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>电话演示</title> <script type="text/javascript"> function showInfo(jsondata){ var jsonobjs = eval(jsondata); var table = document.getElementById("personTable"); for(var y=0; y<jsonobjs.length; y++){ var tr = table.insertRow(table.rows.length); var td1 = tr.insertCell(0); var td2 = tr.insertCell(1); td2.align = "center"; td1.innerHTML = jsonobjs[y].name; td2.innerHTML = "<a href='javascript:Android.call(\""+ jsonobjs[y].phone+ "\")'>"+ jsonobjs[y].phone+ "</a>"; } } </script> </head> <body onload="javascript:Android.showcontacts()"> <table border="0" width="100%" id="personTable" cellspacing="0"> <tr> <td width="30%">姓名</td> <td align="center">电话</td> </tr> </table> </body> </html>
java代码,showcontacts这个方法里面调用js的代码:
package com.example.androidconnecthtml5; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebView; public class PhoneActivity extends AppCompatActivity { private WebView wvVideo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video); wvVideo = (WebView) findViewById(R.id.wv_video); wvVideo.getSettings().setJavaScriptEnabled(true); wvVideo.setWebChromeClient(new WebChromeClient()); //添加js调用类 wvVideo.addJavascriptInterface(new JsInterface(), "Android"); wvVideo.loadUrl("file:///android_asset/JSCallJavaPhoneActivity.htm"); } /** * JavaScript调用Android的方法类 */ class JsInterface { /** * 被js调用,用于加载联系人数据源 */ @JavascriptInterface public void showcontacts() { String json = "[{\"name\":\"天平\", \"phone\":\"18600012345\"}]"; // 调用JS中的方法 wvVideo.loadUrl("javascript:showInfo('" + json + "')"); } } /** * js调用,拨打电话 * * @param phone 手机号码 */ @JavascriptInterface public void call(String phone) { Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone)); if (ActivityCompat.checkSelfPermission(PhoneActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { return; } startActivity(intent); } }
这个时候就会发现showcontacts调用的js代码不起作用了。解决方法,把showcontacts里面的代码改成这样:
wvVideo.post(new Runnable() { @Override public void run() { String json = "[{\"name\":\"天平\", \"phone\":\"18600012345\"}]"; // 调用JS中的方法 wvVideo.loadUrl("javascript:showInfo('" + json + "')"); } });
三、setBuiltInZoomControls(true) 引发的奔溃
这个方法调用以后 如果你触摸屏幕 弹出提示框还没消失的时候 你如果activity结束了 就会报错了。3.0以上 4.4以下很多手机会出现这种情况解决方法:
在activity的onDestroy方法里手动的将webiew设置成 setVisibility(View.GONE);
四、onPageFinished 没调用
这个函数并没有什么卵用,在不同的内核里调用的时机都不一样,有的时候是提前结束,有的时候就迟迟无法结束。如果一定要实现这种功能的话,建议不要这样做,否则卡在那用户迟迟动不了 这种体验不好。或者可以使用onProgressChanged五、后台无法释放js 导致发热耗电
在有些手机你如果webview加载的html里,有一些js一直在执行比如动画之类的东西,如果此刻webview 挂在了后台这些资源是不会被释放用户也无法感知。导致一直占有cpu 耗电特别快,所以如果遇到这种情况请在onStop把setJavaScriptEnabled(false); 在onResume里面设置setJavaScriptEnabled(true)。六、webview 自带的cookie机制
很多人 不知道webview实际上有自己一套完整的cookie机制的,利用好这个可以大大增加对客户端的访问速度。很多人都想要一个效果:网页更新cookie设置完cookie以后不刷新页面即可生效。这个在2.3以下和2.3以上要实现的方法不太一样,所以要做一次兼容
public void updateCookies(String url, String value) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下 CookieSyncManager.createInstance(getContext().getApplicationContext()); } CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.setCookie(url, value); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { CookieSyncManager.getInstance().sync(); } }
七、webView直接执行js会输出到Webview
我之前研究出来的问题:http://blog.csdn.net/niubitianping/article/details/51201553
八、加载网页空白
1.重写了shouldOverrideUrlLoading,但是里面没有重新loadUrl
public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; }
2. 证书错误
重写WebViewClient的onReceivedSslError方法,忽略ssl证书错误private class WebViewListener extends WebViewClient { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed();//忽略ssl证书错误,继续加载网页 } }
3. 缓存问题
解决方法清除app数据,获取重新安装app。代码改进, 重写loadUrl,在每个链接后面添加一个参数
@Override public void loadUrl(String url) { //获取当前时间戳 String random = String.valueOf(System.currentTimeMillis()); if (url.contains("?")) { random = "&random=" + random; } else { random = "?random=" + random; } //添加一个参数,防止缓存 url += random; super.loadUrl(url); }
九、禁止调用系统浏览器打开网页
重写shouldOverrideUrlLoading返回真//在当前Activity打开
private class WebViewListener extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; }
}
十、vue的前端,WebView跳转不了网页
这个坑还是有点大,QQ里面的浏览器可以跳转,UC浏览器可以跳转,就自己的WebView跳转不了,研究了半天,终于还是发现了,需要WebView开启缓存:wvContent.getSettings().setDomStorageEnabled(true);
相关文章推荐
- android开发中webview保存cookie问题的解决
- 自己在使用Android Maps API 开发地图应用程序时遇到的问题,以及解决的办法
- Android开发中webView的使用以及与js交互传值问题
- Android Studio开发RecyclerView遇到的各种问题以及解决
- [开发总结]WebView使用中遇到的一些问题&解决
- Android开发ViewPager的预加载和Fragment的销毁问题,以及tabLayout+ViewPager的使用,tablayout平板适配问题解决
- Eclipse开发Android应用时遇到的问题以及解决方法
- android h5 js 混合开发解决webview加载白屏,不加载网页的问题(硬件加速网页渲染,优化体验)
- 转 [开发总结]WebView使用中遇到的一些问题&解决
- android :webview 解决遇到的跨域问题
- android开发中webview保存cookie问题的解决
- android开发中webview保存cookie问题的解决
- Android Webview遇到的问题——记新版广告墙开发
- android webview与js交互时遇到的问题解决
- [开发总结]WebView使用中遇到的一些问题&解决
- Android开发之如何在WebView中点击链接使用自身打开(解决出现的选择使用第三方应用的问题)
- android开发过程中遇到的问题以及解决办法
- Android WebView开发中无法调音量的问题解决
- 拿什么拯救:Android Studio 时代 继续使用Eclipse开发Android app时遇到的几个问题以及解决办法
- 如何部署Android开发环境以及解决部署中遇到的问题