写这篇文章的主要是因为在实际应用的时候遇到了很多棘手的问题(文章最后部分,交流一下遇到的问题),在这里分享出来让人少走一些弯路,如果有不对的地方直接留言即可

相信一般做Android开发的同学都会或多或少的使用webview,(由于不太了解js,js交互的部分暂时没有)相信有不少人的使用过程是这样的

布局

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/webView"

android:layout_width="match_parent"

android:layout_height="match_parent" >

使用

//设置webview

WebSettings websettings = webView.getSettings();

websettings.setJavaScriptEnabled(true);

websettings.setDomStorageEnabled(true);

websettings.setJavaScriptCanOpenWindowsAutomatically(true);

websettings.setBuiltInZoomControls(false);//

webView.loadUrl(url);

上边这样使用,在使用量少的情况下可能没有问题,但是也给程序留下了不少隐患--内存泄漏,由于webview并没有完全清除掉,一直持有对应的上下文,导致内存无法被回收

说道这里就有了第一种的优化

优化一

既然说没有主动回收,那我们就手动回收在,activity的onDestroy方法中清除webview

public void onDestroy() {

super.onDestroy();

webView.clearHistory();

webView.clearView();

webView.removeAllViews();

webView.destroy();

}

优化二

在需要用到webview的地方直接new一个出来,而不是在.xml文件中定义webview

布局

在布局需要使用webview的地方使用一个FrameLayout代替(其他的容器也可以)

使用

/**

*创建webview并添加到布局容器中

*/

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

WebView webView = WebviewUtil.createNewWebView(context);

FrameLayout frameLayout = findViewById(R.id.xxx);

frameLayout.addView(mWebView);

}

...

/**

*创建webview公共方法

*/

public static android.webkit.WebView createNewWebView(Context context){

android.webkit.WebView webView = new android.webkit.WebView(context.getApplicationContext());

webView.setLayerType(View.LAYER_TYPE_SOFTWARE, new Paint());

webView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));

return webView;

}

/**

*清除webview

*/

public void onDestroy() {

if (null != webView) {

try {

webView.removeJavascriptInterface("xx");

webView.getSettings().setJavaScriptEnabled(false);

webView.loadUrl("about:blank");

webView.loadDataWithBaseURL(null, "", "text/html", "uft-8", null);

ViewParent parent = webView.getParent();

if (parent != null) {

((ViewGroup) parent).removeView(webView);

}

webView.clearHistory();

webView.clearView();

webView.removeAllViews();

webView.destroy();

} catch (Exception e) {

e.printStackTrace();

}

}

super.onDestroy();

}

但是通过以上操作,查看内存并没有被回收.........

优化三 -- 开进程

当你的webview需要的内存很大,但是主进程申请不到更多的内存的情况下可以使用。

此方法各大主流APP基本都是这样操作的,在打开webview页面后,查看此应用的进程是否多开了一个。

开进程的方法也很简单只需要在你需要的activity在AndroidManifest中注册的时候添加“process”属性即可,但是注意进程间的通信;当关闭此activity时杀掉此进程不然内存不能被回收,下次进入时内存累加,最终会导致溢出

android:name=".Activity"

android:process=":remoteView"

/>

如果打开进程的速度慢可以先进行进程的预加载,先启动一个和上边activity同一个进程的service,然后再打开activity

优化四--使用第三方

腾讯的x5内核,具体的优势可以参考腾讯官方文档

最后,再来说说我遇到的问题吧,首先需求是这样的一个页面需要多个统计图(百度的echarts,为了保持两端一致性和多样化的图表需求)每一个图表都需要一个对应的webview

没办法,产品提出来了

1开始使用第一种,崩溃,卡顿问题不断

2使用方法二,解决了大部分的机型,只有蓝绿大厂不行(吐槽中OPPO、vivo)

会出现无故的崩溃,查看logo日志(包括sdk底层logo日志)都只能找到一个内存地址的错误,比如:

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9ffffffff in tid 30218 (Thread-708)

没有其他任何提示,腾讯的bugly,友盟也没有抓取到相关的信息,崩溃中

后来查到两点问题

1、echarts的问题,其中有一个svg渲染(官方是beta版),是为了给低性能设备使用,看情况使用,有些图表会出现点击蓝屏闪烁(只是在webview范围之内),不过亲测内存降低了太多,没有使用前一个带滑块的图表达到了快200M,改为svg之后一直维持在30+M,提升明显,如果使用请自行测试多种机型

2、还是echarts 的问题,数据返回后多次向webview传入了数据导致崩溃,改为一次后暂未发现

以上两个问题目前只在OPPO和vivo手机发现,希望有此需求的小伙伴注意此问题

更多相关文章

  1. mybatisplus的坑 insert标签insert into select无参数问题的解决
  2. 箭头函数的基础使用
  3. NPM 和webpack 的基础使用
  4. Python list sort方法的具体使用
  5. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  6. android 使用html5作布局文件: webview跟javascript交互
  7. Android(安卓)Resource介绍和使用
  8. "Failed to fetch URL https://dl-ssl.google.com/android/repos
  9. 使用NetBeans搭建Android开发环境

随机推荐

  1. 解上篇文章 MyBatis 第一题
  2. 再解 5 题!国庆之后续更,假期愉快!
  3. 什么样的 Java 对象会被当垃圾回收?
  4. Lock锁子类了解一下
  5. 读完《MyBatis技术内幕》,聊几句感触
  6. JVM 家族
  7. 从对象生命周期的经验统计到垃圾回收算法
  8. Nacos集群模式部署
  9. 穿插一个 MyBatis 分页插件 PageHelper
  10. CCNP(ISCW)实验:用命令行配置GRE OVER IPS