当前位置: 首页 > news >正文

【Android 性能优化:内存篇】——WebView 内存泄露治理

背景:笔者在公司项目中优化内存泄露时发现WebView 相关的内存泄露问题非常经典,一个 Fragment 页面使用的 WebView 有多条泄露路径,故记录下。

Fragment、Activity 使用WebView不释放

项目中一个Fragment 使用 Webview,在 Fragment onDestroyView 时候却没有释放,释放 WebView 还不简单嘛,于是笔者在 Fragment 的 onDestroyView 补充了如下代码:

if (webView != null) {ViewGroup parent = (ViewGroup) webView.getParent();if (parent != null) {parent.removeView(webView);}webView.destroy();webview = null;
}

然而,这样其实释放不全,还是抓到其他的泄露路径

如图GC 引用链:AwContents->WebVIew->View.LinsenerInfo->WebViewFragment

原因是使用 WebView的时候,注册了OnFocusChangeListener

webView.setOnFocusChangeListener(new View.OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {//省略}
});

因此,释放 WebView的时候,还需要把注册的一些Listener 释放

WebView 释放不全

上面介绍了释放 WebView 资源的时候释放不全的例子,那么怎样才能将用到的WebView 资源释放完全呢?

笔者封装了一个接口如下:

public void destroyWebView(WebView webView) {try {if (webView != null) {ViewGroup parent = (ViewGroup) webView.getParent();if (parent != null) {parent.removeView(webView);}webView.setOnTouchListener(null);webView.setOnKeyListener(null);webView.setOnFocusChangeListener(null);webView.setWebChromeClient(null);webView.setWebViewClient(null);webView.loadUrl("about:blank");webView.onPause();webView.removeAllViews();webView.destroyDrawingCache();webView.destroy();webView = null;}} catch (Throwable e) {e.printStackTrace();}
}

这样释放真的释放完全了?如果你使用的WebView 还注册了其他的Listener,记得也需要释放

网上,还有说需要调用

webView.pauseTimers();
webView.clearHistory();

上面的接口慎用,因为它们是对全局生效的,不只当前WebView!

按上面两个步骤解决完,笔者以为不会再发生泄漏,谁知道还是抓到第三条泄露路径!!

GC 引用链:AwContents->BannerView->Banner->CardView->Container->AdView->匿名内部类AdListener->WebViewFragment

匿名内部类导致 WebView泄露

按上面描述的引用链,匿名内部类隐式持有外部类 Fragment 的引用,而这个匿名内部类AdShowListener 刚好是 AdView 持有的, AdView 本质上是一个 WebView.

解法很常规:把匿名内部类改为静态内部类,然后静态内部类里使用的 Fragment 改为弱引用,并且 Fragment 销毁的时候,AdShowListener 置空。

到此,笔者以为不会再发生内存泄露了,怎知,还是抓到了,这次抓的是包裹 Fragment 的Activity 作为 Context 被 webview 持有

意不意外,惊不惊喜?

GC 引用链:AwContents->WebView->WebViewActivity, WebViewActivity 作为 Conext 被 WebView 持有

因为 Fragment 初始化 WebView 的时候 使用了 getActivity(),context 一直被 WebView 内核持有,笔者猜测部分系统会有这种问题。这种问题是否无解了?山重水复疑无路,柳暗花明又一寸,笔者意外发现有个类 MutableContextWrapper 可以使用。

MutableContextWrapper 切换 Context

初始化 WebView 的时候使用AppContext,在 Activity 使用 Webview 的时候切换为 Activity,最后销毁 WebView 之前再切换回 AppContext

为什么在Activity 使用WebView的时候切换到Activity 呢?因为WebView 中的可能有些场景依赖 Activity 如:弹窗Dialog,Context 为AppContext 会发生崩溃。

private WebView webview;
//初始化Webview
MutableContextWrapper contextWrapper = new MutableContextWrapper(getAppContext());
webview = new WebView(contextWrapper);//在Activity中使用
private WebView acquireWebView(Activity activity) {//缓存中的webviewMutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();contextWrapper.setBaseContext(activity);return webView;
}//销毁之前public void recycleWebView(WebView webView) {if (webView == null) {return;}MutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();contextWrapper.setBaseContext(getAppContext());destroyWebView(webview);}//销毁 webview 的接口
public void destroyWebView(WebView webView) {try {if (webView != null) {ViewGroup parent = (ViewGroup) webView.getParent();if (parent != null) {parent.removeView(webView);}webView.setOnTouchListener(null);webView.setOnKeyListener(null);webView.setOnFocusChangeListener(null);webView.setWebChromeClient(null);webView.setWebViewClient(null);webView.loadUrl("about:blank");webView.onPause();webView.removeAllViews();webView.destroyDrawingCache();webView.destroy();webView = null;}} catch (Throwable e) {e.printStackTrace();}
}

至此,没有再抓到泄露路径。

总结

本文列举了项目中治理 WebView 内存泄露的手段:

1)Fragment、Activity 销毁时释放WebView。

2)释放WebView 需要释放完全,WebView 注册的各种监听器都需要释放。

3)同时要考虑Fragment、Activity 有没用到匿名内部类,如果有要改成静态内部类,并且要静态内部类有使用Fragment、Activity的话要使用弱引用。

4)初始化 WebView 的时候使用AppContext,在 Activity 使用 Webview 的时候切换为 Activity,最后销毁 WebView 之前再切换回 AppContext。

相关文章:

【Android 性能优化:内存篇】——WebView 内存泄露治理

背景:笔者在公司项目中优化内存泄露时发现WebView 相关的内存泄露问题非常经典,一个 Fragment 页面使用的 WebView 有多条泄露路径,故记录下。 Fragment、Activity 使用WebView不释放 项目中一个Fragment 使用 Webview,在 Fragm…...

C++入门(一)

文章目录 前言一、C的发展史二、c关键字二、c命名空间1、代码演示2、::(域作用限定符) 和namespace(命名空间)3、命名空间可以嵌套使用4、同一个工程中的相同名字的命名空间 三、c的输入&&输出1、iostream(输入…...

C#控制台程序读取输入按键非阻塞方式

参考内容: http://www.dutton.me.uk/2009-02-24/non-blocking-keyboard-input-in-c/ 相关代码: while (true) {if (Console.KeyAvailable){ConsoleKeyInfo key Console.ReadKey(true);switch (key.Key){case ConsoleKey.F1:Console.WriteLine("Y…...

小程序框架->框架,视图层,生命周期(逻辑层)

框架视图层生命周期(逻辑层) 1.框架 小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。 整个小程序框架系统分为两部分:**[逻辑层](https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/)…...

Spring framework Day14:配置类的Lite模式和Full模式

前言 Lite模式和Full模式是指在软件或系统中的不同配置选项。一般来说,Lite模式是指较为简洁、轻量级的配置,而Full模式则是指更加完整、功能更丰富的配置。 Lite模式通常会去除一些不常用或占用资源较多的功能,以提高系统的运行效率和响应…...

公司要做大数据可视化看板,除了EXCEL以外有没有好用的软件可以用

当企业需要进行大数据可视化看板的设计和开发时,除了Excel,还有许多其他强大且适合大数据可视化的软件工具。以下是几种常用的好用软件,以及它们的特点和优势,供您参考。 一、Datainside 特点和优势: - **易于使用**…...

掌握深入挖掘数据本质的方法

文章目录 掌握深入挖掘数据本质的方法1. 确定数据类型2. 数据清洗3. 数据可视化4. 探索性数据分析5. 特征工程6. 机器学习算法7. 自然语言处理 📕我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华…...

MyBatisPlus的学习项目页面

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息 类名驼峰转下划线作为表名 名为id的字段作为主键 变量名驼峰转下划线作为表的字段名 常见注解 TableName:用来指定表名 Tableld:用来指定表中的主键字段信息 Tabl…...

基于EtherCAT的机器人多轴同步运动控制

随着工业自动化的发展,机器人在生产线上的应用越来越广泛。为了实现高效、精确的运动控制,机器人的多轴运动必须能够实现同步操作,它能够提高机器人的运动精度和稳定性,实现更高效的生产线操作。同时,它也为机器人的协…...

彩虹易支付 9.27 最新版加订单查询 sy 更新版

彩虹易支付 9.27 最新版加订单查询 sy 更新版 修复客服 2023/09/25: 1. 新增支付宝红包支付插件 2. 新增支付宝 APP 支付转 H5 支付 3. 更新了几个支付插件 安装教程: 环境:php7.2 上传后访问域名进行安装即可 源码下载:ht…...

python树状打印项目路径

学习这个的需求来自于,我想把项目架构告诉gpt问问它,然后不太会打印项目架构😂 联想到Linux的tree指令 import osclass DirectoryTree:def __init__(self, path):self.path pathdef print_tree(self, methoddefault):if method default:sel…...

mysql误删误操作恢复数据,比传统方式和binlog2sql更快速用的恢复方式-reverse_sql恢复数据(单表多表)

场景: 误操作删除了某个表的数据,本文只讲工具的使用,首先自己通过mysqlbinlog或者记录找到误操作的时间范围:开始时间和结束时间,已经确定好是哪个binlog了下面以误删为例。 查看binlog是否开启 show variables like …...

CORE: Cooperative Reconstruction for Multi-Agent Perception 论文阅读

论文连接 CORE: Cooperative Reconstruction for Multi-Agent Perception 0. 摘要 本文提出了 CORE,一种概念简单、有效且通信高效的多智能体协作感知模型。 从合作重建的新颖角度解决了该任务: 合作主体共同提供对环境的更全面的观察整体观察可以作为…...

MySQL连接方式: Unix套接字 TCP/IP

今天连接mysql数据库使用mysql -u root -p指令的时候遇到了这个问题: 解决之后来总结一下mysql的连接方式 文章目录 1. Unix套接字(或Windows命名管道)特点:场景: 2. TCP/IP特点:场景: 3.对比总…...

TSINGSEE青犀智慧城市数字基座解决方案,助力城市数字化转型

一、行业背景 我国“十四五”规划纲要中提出,分级分类推进新型智慧城市建设,将物联网感知设施、通信系统等纳入公共基础设施统一规划建设,推进市政公用设施、建筑等物联网应用和智能化改造。完善城市信息模型平台和运行管理服务平台&#xf…...

【JavaEE】初识网络

网络初识 文章目录 网络初识网络发展史独立模式网络互连局域网LAN广域网 网络通信基础IP地址端口号格式 协议五元组协议分层OSI七层模型TCP/IP五(四)层协议1.物理层2.数据链路层3.网络层4.传输层5.应用程序 网络设备所在的分层封装和分用例子发送方接收方…...

UGUI交互组件ScrollBar

一.ScrollBar的结构 对象说明Scrollbar挂有Image和Scrollbar组件的主体对象Sliding Area表示滑动范围Handle滑块 二.Scrollbar的属性 属性说明Handle Rect控制柄对象的引用Direction拖动控制柄时滚动条值增加的方向Value滚动条的当前值,范围为 0.0 到 1.0Suze控制柄…...

DamiBus v0.51 发布

DamiBus,专为本地多模块之间通讯解耦而设计(尤其是未知模块、隔离模块、领域模块)。零依赖,特适合 DDD。 特点 结合 Bus 与 RPC 的概念,可作事件分发,可作接口调用,可作响应订阅。 支持事务传…...

[OpenJDK:环境变量配置]:填充Profile并修改默认配置

文章目录 一:背景:安装hadoop启动提示未找到JAVA_HOME1.1:配置Hadoop的Java环境变量 二:排查-定位解决2.1:查看环境变量配置发现没有JAVA_HOME2.1.1:解决:查看java安装目录2.1.2:再次…...

连接mysql报错 :Host ‘xxx.xx.x.x‘ is not allowed to connect to this MySQL server

排查思路 命令行连接mysql 我是安装在本地docker容器中的,可以使用一下命令直接连接 docker exec -it mysqldb mysql -u root -p其中mysqldb是我的mysql容器名字,后面跟随mysql的连接命令,然后输入密码即可。 如果没有设置过密码&#xff0c…...

Qt 布局(QSplitter 类QDockWidget 类) 总结

一、QSplitter 类(窗口分割) QSplitter类是一个Qt框架提供的基础窗口控件类,用于分割窗口,使得用户可以通过拖动分隔条来调节子窗口的大小。QSplitter在用户界面设计中非常常见,经常用于划分窗口区域,使得程序可以同时显示多个子…...

git-ssh-key协议同步文件

生成秘钥 ssh-keygen -t rsa ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/c/Users/Beza/.ssh/id_rsa): /c/Users/Beza/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphrase (empty for no passphrase): …...

2018-2019 ACM-ICPC, Asia Nanjing Regional Contest G. Pyramid(组合数学 计数)

题目 t(t<1e6)组样例&#xff0c;每次给定一个n(n<1e9)&#xff0c;统计边长为n的上述三角形的等边三角形个数 其中等边三角形的三个顶点&#xff0c;可以在所有黑色三角形&白色三角形的顶点中任取&#xff0c; 答案对1e97取模 思路来源 申老师 & oeis A0003…...

C++学习——string 详解(即C++字符串详解)

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 一、定义string变量的方法 C增强了对字符串的支持&#xff0c;除了可以使用C风格的字符串&#xff0c;还可以使用内置的 string 类。 string是类&#xff0c;而不是基本数据类型。虽…...

LeetCode 1 两数之和

题目描述 链接&#xff1a;https://leetcode.cn/problems/two-sum/?envTypefeatured-list&envId2ckc81c?envTypefeatured-list&envId2ckc81c 难度&#xff1a;简单 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 targ…...

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程前言准备工具anaconda/cuda/cudnnanaconda创建环境(选做)安装原…...

【1day】用友U8Cloud未授权访问漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现...

基于单片机智能汽车仪表设计系统

基于单片机的汽车智能仪表的设计 摘要&#xff1a;汽车的汽车系统。速度测量以及调速是我们这次的设计所要研究的对象&#xff0c;本次设计的基础核心的模块就是单片机&#xff0c;其应用的核心的控制单元就是stc89c52单片机&#xff0c;用到的测速模块是霍尔传感器&#xff0c…...

java double 保留两位小数

在Java中&#xff0c;你可以使用 DecimalFormat 或 String.format 来保留 double 类型的数字两位小数。以下是两个例子&#xff1a; 使用 DecimalFormat import java.text.DecimalFormat;public class Main {public static void main(String[] args) {double number 123.456…...

计网第六章(应用层)(三)(文件传输协议FTP)

一、基本概念 将某台计算机中的文件通过网络传送到可能相距很远的另一台计算机中即文件传送。 FTP就是因特网上使用得最广泛的文件传送协议。采用客户/服务器方式。 FTP提供交互式的访问&#xff0c;允许客户指明文件的类型和格式&#xff08;如指明是否使用ASCII码&#xf…...

怎样安全做黑色彩票网站/台州关键词优化平台

服务器电源规范解析服务器的动力之源、稳定之源服务器电源有ATX电源和SSI电源两大类产品。ATX电源就是我们平常台式机使用的电源&#xff0c;在服务器领域这种电源主要被用在低端的塔式服务器及工作站上。而SSI电源则是Intel推出的一种服务器专用电源规范。台式PC电源的发展经过…...

南昌建站/广告营销策划

作者 | 雷哥 编辑 | 小西瓜职场中&#xff0c;大家是否遇到这样的情况&#xff0c;需要把数字“1,2,3......” 转换为 大写的“壹贰叁...”&#xff0c;大家都有哪些方法可以实现呢&#xff1f;今天雷哥就跟大家分享下Excel中&#xff0c;大小写的那些事~01 NUMBERSTRING函数NU…...

网站服务器有什么区别/培训班该如何建站

JsoupJsoup 是一款轻量高效的 html 文档解析工具&#xff0c;可类比 xml 中的 dom4j 、jdomJsoup中的基本类DocumentHtml 整个文档在内容中的数据结构&#xff0c;继承 ElementElement标记元素的数据结构 &#xff0c;继承 NodeElementsElement 的集合&#xff0c;继承 ArrayLi…...

给企业开发网站/广告推广软文案例

是这样的&#xff0c;我最近遇到的问题就是&#xff0c;我用JAVA连接数据库的一个表格获得里面的序列号&#xff0c;现在我有一个文件夹里面有这里面所有数据的状态(PASS/FAIL)&#xff0c;我也能提取这个文件夹里面所有的文件名&#xff0c;我现在要怎么把这两个程序结合&…...

淘客网站怎么做排名/个人博客网站搭建

kubernetes job tags: job,cronjob 《相助》一部关于黑人种族主题电影 文章目录kubernetes job1. 简介2. 参数3. job创建过程细讲4. Job Controller 对并行作业的控制方法5. Job Controller 的工作原理6. 三种job方法6.1 外部管理器 Job 模板6.2 拥有固定任务数目的并行 Job6.…...

冲压加工瑞安有做网站吗/网站接广告平台

“忆享聚焦”栏目第十三期来啦&#xff01;本栏目汇集近期互联网最新资讯&#xff0c;聚焦前沿科技&#xff0c;关注行业发展动态&#xff0c;筛选高质量讯息&#xff0c;拓宽用户视野&#xff0c;让您以最低的时间成本获取最有价值的行业资讯。 目录 行业资讯 1. 微软深夜放炸…...