在 Android H 版本之前,WebView存在一个令人恶心的BUG。

这个BUG的描述是这样子的:
1,如果传递给WebView的Context引用是 Activity’s Context,当退出这个Activity时,Activity不能被回收导致内存泄漏
2,如果传递给WebView的Context引用是Appliaction’s Context,这个WebView不能被显示dialog并开启其他的Activity,这明显不是我们 want 的

要解决这个问题,产生了一系列的解决办法:
第1种,在单独的进程中启动WebView,一旦WebView完成了使命,就可以杀死进程,以避免内存泄漏,如果WebView进错需要与主进程交换数据,则需要实现一些AIDL接口,下面是实现思路和举例
基本步骤
[1]. Basics基本步骤:

  • To create a webview, a reference (say an activity) is needed.
  • To kill a process:
    `android.os.Process.killProcess(android.os.Process.myPid()); can be called.`

[2]. Turning point 重点思想:
默认情况下,所有活动在一个应用程序中在同一进程中运行 (该过程由包名称定义)。 但:
Different processes can be created within same application.

所以,如果为活动创建了不同的进程,则其上下文可用于创建WebView。 当这个进程被杀死时,所有引用这个活动的组件(在这种情况下是webview)被杀死,最主要的部分是:
GC is called forcefully to collect this garbage (webview).

[3]. Code for help: (one simple case)
Total two activities: say A & B

Manifest file:

<application
        android:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:process="com.processkill.p1" // can be given any name android:theme="@style/AppTheme" ><activity
            android:name="com.processkill.A"android:process="com.processkill.p2"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity
            android:name="com.processkill.B"android:process="com.processkill.p3"android:label="@string/app_name" ></activity></application>

Start A then B
A > B

B 是带有WebView的
当在活动B上按backKey时,调用onDestroy:

@Overridepublic void onDestroy() {android.os.Process.killProcess(android.os.Process.myPid());super.onDestroy();}

and this kills the current process i.e. com.processkill.p3
并删除引用它的webview

需要注意的是:
使用此kill命令时要格外小心。 不要在Activity(在这种情况下为ActivityB)中实现任何静态方法。 不要使用任何其他任何引用此Activity(因为它将被杀死,不再可用)。

第2种,重写WebView,代码如下
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.AttributeSet;
import android.webkit.WebView;
import android.webkit.WebViewClient;public class NonLeakingWebView extends WebView {private static Field sConfigCallback;static {try {sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");sConfigCallback.setAccessible(true);} catch (Exception e) {// ignored}}public NonLeakingWebView(Context context) {super(context.getApplicationContext());setWebViewClient(new MyWebViewClient((Activity) context));}public NonLeakingWebView(Context context, AttributeSet attrs) {super(context.getApplicationContext(), attrs);setWebViewClient(new MyWebViewClient((Activity) context));}public NonLeakingWebView(Context context, AttributeSet attrs, int defStyle) {super(context.getApplicationContext(), attrs, defStyle);setWebViewClient(new MyWebViewClient((Activity) context));}@Overridepublic void destroy() {super.destroy();try {if (sConfigCallback != null)sConfigCallback.set(null, null);} catch (Exception e) {throw new RuntimeException(e);}}protected static class MyWebViewClient extends WebViewClient {protected WeakReference<Activity> activityRef;public MyWebViewClient(Activity activity) {this.activityRef = new WeakReference<Activity>(activity);}@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {try {final Activity activity = activityRef.get();if (activity != null)activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));} catch (RuntimeException ignored) {// ignore any url parsing exceptions}return true;}}
}
///OnActivity finish or destroy call
@Overridepublic void finish() {webView.destroy();super.finish();}

但是这种方法被认为:如果你的APP只有一个WebView,这种方法可能会很有效的规避内存泄漏,否则,每一个带有WebView的Activity都会出现leak,并且举出的原因

Please check the code:
Line 209-215
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.5_r1/android/webkit/BrowserFrame.java#BrowserFrame.ConfigCallback

Line 298-301
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.5_r1/android/view/ViewRoot.java#ViewRoot.addConfigCallback%28android.content.ComponentCallbacks%29

这两处的源码阐述了,sConfigCallbacks的声明是一个静态的ArrayList并且用来保存WebView实例中BrowserFrame.ConfigCallback的引用。

当每次点击Back返回键并且onDestroy()在WebviewActivity中被调用,则BrowserFrame.sConfigCallback设置为null,然后,如果我们开启另外一个WebViewActivity,那么就会有一个WebView被创建,这时候如果BrowserFrame.sConfigCallback为Null,那么新的一个BrowserFrame.sConfigCallback实例被创建并被添加到静态ArrayList中,其中包括成员变量mWindowManger,mWindowManger间接的引用了WebViewActivity,所以内存泄漏发生了。

在Android L 5.1版本中,还存在一个WebView内存泄漏的问题,该问题的描述是这样的:

每新打开一次WebViewActivity,就会发生就会发生一次改Webview实例无法释放,新增一个对象。

该问题的分析可以点开连接:
https://coolpers.github.io/webview/memory/leak/2015/07/16/android-5.1-webview-memory-leak.html

总结这个泄漏的原因就是,webView的onDestroy 发生在 onDetach 之前。
在Android 5.1之前,不存在判断onDestroy,可以正常调用执行

if (mComponentCallbacks != null) {mContext.unregisterComponentCallbacks(mComponentCallbacks);mComponentCallbacks = null;}

在Android 5.1时,会提前判断

f (isDestroyed()) return;

不能unregist,导致内存泄漏。

这个新的内存泄漏的规避方法如下:
在destroy之前,把webview 从 parent 中 remove 掉,同样可以提前detach。

  protected void onDestroy() {if (mWebView != null) {((ViewGroup) mWebView.getParent()).removeView(mWebView);mWebView.destroy();mWebView = null;}super.onDestroy();}

[WebView] - WebView leaked相关推荐

  1. Android开发继承webview,WebView如何从当前的Android主题继承颜色?

    此问题最初发布在谷歌版主上,用于上周举行的AndroidDev办公时间环聊.问题实际上是现场回答,如果你愿意,你可以在这里观看.我在这里发帖,因为他们似乎对它很感兴趣,而且我有更多的空间来详细阐述. ...

  2. html5字体修改webview,WebView中修改字体

    一般情况下我们做加载网页都是返回一个url,我们进行加载.各种各样的样式都已经在网页中做了处理.但是,也会碰到一些情况,需要我们加载代码片段.还有修改一些样式,比如:修改网页中的字体.当然,本文中的修 ...

  3. android使用webview时按后退退出的问题

    使用webview打包图片站点http://www.gg4493.cn,代码都好了,具体如下 public class MainActivity extends ActionBarActivity { ...

  4. Android WebView使用与JavaScript使用

    WebView基本使用 WebView是View的一个子类,可以让你在activity中显示网页. 可以在布局文件中写入WebView:比如下面这个写了一个填满整个屏幕的WebView: <?x ...

  5. Android开发学习笔记:WebView 一

    WebView(网络视图)能加载显示网页,可以将其视为一个浏览器.它使用了WebKit渲染引擎加载显示网页,实现WebView有以下两种不同的方法: 第一种方法的步骤: 1.在要Activity中实例 ...

  6. 转 Android开发学习笔记:浅谈WebView

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liangruijun.blog.51cto.com/3061169/647456 ...

  7. android webview mailto,Webview email link (mailto)

    问题 I have a view and view the site has malito code to send email. When I open the link opens in an e ...

  8. 大叔也说Xamarin~Android篇~原生登陆与WebView的网站如何共享Session

    回到目录 事情是这样的,我们最近开了一个APP,主要使用xamarin做了一个登陆,它与服务器API进行数据通讯,当用户名密码正确去,跳转到新的activity,并在webview控件中打开服务端的H ...

  9. android webview详情,Android中的WebView详细介绍

    Android中WebView的详细解释: 1. 概念: WebView(网络视图)能加载显示网页,可以将其视为一个浏览器.它使用了WebKit渲染引擎加载显示网页. 2. 使用方法: (1).实例化 ...

最新文章

  1. 不需编程/无需写代码的中文英文文本分析教程,免费傻瓜式,多图预警
  2. 解决IE无法查看源文件问题
  3. MySQL第8天:MySQL索引优化分析之SQL慢
  4. C++中变量使用前一定要初始化
  5. 栈的链式存储及其基本运算
  6. spring mvc学习(39):restful的crud实现删除方式
  7. 21 FI配置-财务会计-为非征税事务分配税务代码
  8. PCL中点云可视化:坐标字段、随机、单一颜色、法向量
  9. java解析xml报文_java 如何解析http请求返回的xml报文
  10. 我的Spring MVC第一个应用
  11. python怎么做情感分析_如何用python进行情感分析
  12. python实验室公众号_区块链研究实验室 | 使用Python编写Tendermint应用程序
  13. 【ArcGIS操作】2 高级编辑篇
  14. 详解健康体检信息管理系统技术开发
  15. Java 内部类与外部类的关系
  16. [网络安全自学篇] 六十.Cracer第八期——(2)五万字总结Linux基础知识和常用渗透命令
  17. Java用jxl对表格的数值进行比对
  18. 2021年安全员-C证(陕西省)考试资料及安全员-C证(陕西省)新版试题
  19. 微信公众号排查“该公众号提供的服务出现故障,请稍后再试”问题
  20. Windows下编译语音识别引擎Wenet

热门文章

  1. 互联网晚报 | 11月3日 星期三 | 头条西瓜等业务并入抖音;菜鸟联合天猫上亿元补贴快递员;雅虎宣布正式退出中国市场...
  2. 从哈密尔顿路径谈NP问题
  3. iphone计算机的声音怎么办,苹果计算机安装win10系统的扬声器无声音该怎么解决...
  4. 如何使用Python api 函数写股票策略
  5. 在线编辑、在线预览、在线转换,基于wps.js + java + react / vue,无需任何插件,零安装
  6. php selectradio和checkbox默认选择的实现方法
  7. 大前端学习笔记--持续随缘更新
  8. java五子棋的重要算法讲解_[Java五子棋小游戏-Ai算法精讲以及实现]-02--高级算法初步...
  9. pb中数据窗口函数小结
  10. matlab 极限积分,实验二MATLAB中的极限和微分积分运算