Android5.1系统WebView内存泄漏场景
问题现象
(该文章,引自零号路的私人博客,本人在浏览框架的开发过程中,用该方式,规避了内存泄露的问题。)
在Android5.1系统中,会发现App存在 WebView 泄漏情况,还比较严重。并且只是发生在 Android 5.1 系统。
GC roots 如下:
每新打开一次这个WebViewActivity,就会发生就会发生一次改Webview实例无法释放,新增一个对象。
上图中的两个 AppSearchWebView实例,就是由于打开了两次导致。
问题分析
出现了这个问题分析起来还是比较简单的,根据这个引用关系,我们可以直观的看到是由于 Appsearch(extends Application)的 mComponentCallbacks 一直在强引用AWComponentCallbacks,导致无法释放。然后AWComponentCallbacks -> AWContents > AppSearchWebView。
通过分析代码发现关键在于 AwContents 这里的 AwComponentsCallbacks 为什么没有释放。
@Override
public void onAttachedToWindow() {
if (isDestroyed()) return;
if (mIsAttachedToWindow) {
Log.w(TAG, "onAttachedToWindow called when already attached. Ignoring");
return;
}
......
mComponentCallbacks = new AwComponentCallbacks();
mContext.registerComponentCallbacks(mComponentCallbacks);
}
@Override
public void onDetachedFromWindow() {
if (isDestroyed()) return;
if (!mIsAttachedToWindow) {
Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
return;
}
......
if (mComponentCallbacks != null) {
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mComponentCallbacks = null;
}
......
}
看这段代码看不出来什么问题,onAttach的时候 register,detach的时候 unregister, 不会存在问题。
但是为什么呢?
难道是由于 if (isDestroyed()) return 这条return引起的?
当调用 Webview.destroy() 后 这个判断 返回true。
我们看下哪里调用了 webview.destroy()
// source from WebViewActivity
@Override
protected void onDestroy() {
super.onDestroy();
if (mWebView != null) {
mWebView.destroy();
}
}
很多应用应该都是这么做的,包括系统浏览器,在Activity destroy的时候,调用 webview的destroy。并且一直工作的很好。
通过调试发现,确实是由于此调用导致的。onDestroy 发生在 onDetach 之前。
那为什么 android 5.1 之前的代码没有问题呢?
看下代码:
// AwContents.java
@Override
public void onDetachedFromWindow() {
if (!mIsAttachedToWindow) {
Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
return;
}
......
if (mComponentCallbacks != null) {
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mComponentCallbacks = null;
}
......
}
相对于 5.1 的代码少了那句 if (isDestroyed()) return;
规避方法
解决方案可以:在destroy之前,把webview 从 parent 中 remove 掉,同样可以提前detach。
protected void onDestroy() { if (mWebView != null) { ((ViewGroup) mWebView.getParent()).removeView(mWebView); mWebView.destroy(); mWebView = null; } super.onDestroy(); }
Android5.1系统WebView内存泄漏场景的更多相关文章
- Android内存优化14 内存泄漏常见情况5 特殊对象造成的内存泄漏 WebView内存泄漏
WebView造成内存泄露 关于WebView的内存泄露,因为WebView在加载网页后会长期占用内存而不能被释放,因此我们在Activity销毁后要调用它的destory()方法来销毁它以释放内存. ...
- 安卓android WebView Memory Leak WebView内存泄漏
Android WebView Memory Leak WebView内存泄漏 在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面 ...
- Js中常见的内存泄漏场景
常见的内存泄漏场景 内存泄漏Memory Leak是指程序中已动态分配的堆内存由于疏忽或错误等原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果.内存泄漏并非指内 ...
- js的内存泄漏场景、监控以及分析
内存泄漏 Q:什么是内存泄漏? 字面上的意思,申请的内存没有及时回收掉,被泄漏了 Q:为什么会发生内存泄漏? 虽然前端有垃圾回收机制,但当某块无用的内存,却无法被垃圾回收机制认为是垃圾时,也就发生内存 ...
- Android WebView Memory Leak WebView内存泄漏
在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用 ...
- JVisualVM 模拟一次内存泄漏场景分析
首先贴一段内存泄漏的代码并且执行.(内存泄漏:GC回收不掉的实例对象) package com.example.demo.memoryLeakDemo; import com.example.demo ...
- 系统剖析Android中的内存泄漏
[转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...
- 解决Android5.0以下Dialog引起的内存泄漏
最近项目开发中,开发人员和测试人员均反应在android5.0以下手机上LeakCanary频繁监控到内存泄漏,如下图所示,但凡用到Dialog或DialogFragment地方均出现了内存泄漏. 如 ...
- Android开发之漫漫长途 番外篇——内存泄漏分析与解决
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
随机推荐
- Java - 双冒泡法排序
最开始的代码 我采用的是我原来进行快速排序所用的方法,一直做不出来. 为什么我会采用原来快速排序的方法?因为我的记忆中好像就是这样的,因此我根据记忆中的快速排序在进行改变,然而,却无法真正的写出双冒泡 ...
- 1、突然对jQuery的心血来潮
起因 随着饿百新零售项目一期的告一段落,算是暂时从加班的修罗场里面解放出来了,于是就想搞点事情,正好看项目js库的时候发现了躺在角落的jQuery,想到当初看源码的时候断断续续的没有看完一直是心头的遗 ...
- 【COOKIE 与 SESSION】
一.相关概念 cookie的出现,解决http协议无状态特性 由于http协议无法保持状态,但实际情况,我们却又需要"保持状态",因此cookie就是在这样一个场景下诞生. 举例: ...
- XAML: 自定义控件中事件处理的最佳实践
在开发 XAML(WPF/UWP) 应用程序中,有时候,我们需要创建自定义控件 (Custom Control) 来满足实际需求.而在自定义控件中,我们一般会用到一些原生的控件(如 Button.Te ...
- python小练习(自己瞎倒腾)
python小练习 在网上无意中看到一个问题,心血来潮写了写,觉得比较有意思,以后遇到这种有意思的小练习也记录下. #!/usr/bin/env python # -*- coding:utf-8 - ...
- python 之进程篇
多线程给我们的感觉 1.因为GIL的存在,一个进程的多线程同一时刻只能进去一个,感觉是假的并发 2.只适合I/O密集型的任务 3.针对计算密集型,就挂了(变成串行了) 在python中想要充分利用多核 ...
- require和require_once的区别
require 的使用方法如 require("./inc.php"); .通常放在 PHP 程式的最前面,PHP 程式在执行前,就会先读入 require 所指定引入的档案,使它 ...
- Spring mybatis源码学习指引目录
前言: 分析了很多方面的mybatis的源码以及与spring结合的源码,但是难免出现错综的现象,为了使源码陶冶更为有序化.清晰化,特作此随笔归纳下分析过的内容.博主也为mybatis官方提供过pul ...
- BZOJ 3265: 志愿者招募加强版 [单纯形法]
传送门 一个人多段区间,一样.... 不过国家队论文上说这道题好像不能保证整数解.... #include <iostream> #include <cstdio> #incl ...
- 除了使用URLSearchParams处理axios发送的数据,但是兼容性不好,其他的兼容方法
在使用axios这个ajax插件的时候,我们有些时候会遇到一些问题,比如:数据格式不正确 以最简单的例子为基础(这里使用post方法): 在上面的例子中我们直接调用axios的post方法,传给后台的 ...