Android常见内存泄漏场景总结
一、非静态内部类造成的内存泄漏
造成原因:非静态内部类默认会持有外部类的引用,如果内部类的生命周期超过了外部类就会造成内存泄漏。
场景:当Activity销毁后,由于内部类中存在异步耗时任务还在执行,导致Activity实例一直被内部类持有无法被回收,造成内存泄漏
例如:
//TestActivity
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new Thread(new Runnable() {@Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}).start();}});
此时点击返回键关闭当前Activity,页面正常回退,但匿名内部类中还有耗时任务执行,如果耗时任务执行完之后要刷新页面还会造成异常导致app闪退。
解决办法:不使用匿名内部类,并且使用static关键字修饰内部类(static修饰的内部类不持有外部类的引用,也自然不会造成上面的内存泄漏),如果内部类中需要使用外部类的资源,可以使用弱引用的方式持有外部类。
优化后的代码如下:
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new Thread(new MyRunnable()).start();}});static class MyRunnable implements Runnable{@Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
二、静态成员变量造成的内存泄漏
造成原因:静态成员变量的生命周期 = 应用程序的生命周期,如果该静态成员应用的变量生命周期 < 改静态变量则会造成内存泄漏
场景:静态成员变量持有了一个耗费资源过多的实例(Activity,Fragment)
例如:
public class Person {private static Activity mActivity;Person(Activity activity){mActivity = activity;}
}
此时点击返回键关闭当前Activity,但Person类中的mActivity静态变量持有当前Activity的引用,导致改Activity对象本该被回收而没被回收,导致内存泄漏
解决办法:
- 尽量避免
Static成员变量引用资源耗费过多的实例(如Context) - 如果必须使用Context,可以使用Application的Context
- 使用弱引用代替强引用持有
三、单例模式造成的内存泄漏
造成原因:单例模式由于其具有静态特性,导致其生命周期 = 应用程序生命周期,如果单例中持有别的类的实例,就会造成内存泄漏
场景:单例模式中持有一个耗费资源过多的实例(Context)
例如:
public class SingleInstance{private static SingleInstance instance;private Context mContext;private SingleInstance(Context context) {this.mContext = context; // 传递的是Activity的context}public SingleInstance getInstance(Context context) {if (instance == null) {instance = new SingleInstance(context);}return instance;}
}
此时由于单例中持有传入的Activity实例,倒是该Activity关闭时,资源得不到回收,从而造成内存泄漏
解决办法:
使用Application的Context代替Activity的Contex
四、Handler造成的内存泄漏
造成原因:当使用非静态内部类(包含匿名内部类)创建Handler时,Handler会持有外部类的对象,如果Handler中还有消息没执行完,此时创建Handler的Activity关闭就会造成内存泄漏。通常由于子线程持有handler的引用(因为要发消息给handler来更新界面),handler又持有activity的引用,从而导致activity不能正常被回收,造成内存泄漏
场景:Activity中通过一个子线程异步请求网络数据,请求成功后更新当前页面。
例如:
//MainActivity.javaprivate Handler mHandler = new Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {//更新页面}};//成功获取到网络数据更新页面private void handleData(String data){Message message = Message.obtain();message.obj = data;mHandler.sendMessage(message);
}
解决办法:
1、静态内部类+弱引用
static class MyHandler extends Handler {WeakReference<Activity > mReference;MyHandler(Activity activity) {mReference= new WeakReference<Activity>(activity);}@Overridepublic void handleMessage(Message msg) {final Activity activity = mReference.get();if (activity != null) {//更新页面}}
}
2、activity销毁时,及时清理消息
@Override
protected void onDestroy() {super.onDestroy();if (mHandler != null) {mHandler.removeCallbacksAndMessages(null);}
}
五、多线程造成的内存泄漏
造成原因:上面一和四其实也是多线程造成内存泄漏的场景,主要是子线程中持有外部类(例如Activity)的引用,让后子线程的生命周期又和Activity不同步,从而造成activity被销毁时子线程中的任务还在执行,从而导致activity的资源迟迟得不到回收造成内存泄漏。
六、集合类造成的内存泄漏
造成原因:当我们把一些对象的引用加入到集合对象(例如常用的ArrayList),当我们不需要改对象时,没有从集合中清理掉改对象的引用,这样集合就会越来越大,如果集合时static的那问题就更严重了。
场景:学生管理系统中需要统计学生信息,使用一个集合存储学生信息,信息统计完成,把信息存入数据库后就不需要学生对象信息了,但是没及时清理掉集合,导致学生对象得不到回收,造成内存泄漏
例如:
// 通过 循环申请Person 对象并放入集合
List<Person> personList = new ArrayList<>();for (int i = 0; i < 10; i++) {Person p = new Person();personList.add(p);
// 虽释放了集合元素引用的本身:p=null
// 但集合List仍然吃药后该对象引用,所以依然不可回收该对象p = null;
}
解决办法:在不使用改集合时,清理集合并把集合置为空
// 释放personList
personList.clear();
personList=null;
七、WebView造成的内存泄漏
造成原因:WebView中可能会进行大量的网络请求,加载大量的资源,从而使得内存占用过高,当我们推出承载Webview的Activity时,没有正确的释放WebView中的资源,导致内存泄漏。
例如:新闻列表页面使用WebView加载一个h5页面,此时会进行大量网络请求加载新闻图片内容,当我们回退该页面时,加载的资源没正确释放导致内存泄漏
解决方案:不使用xml定义webview,通过代码的形式,传入Application的Context然后在承载webview的页面销毁时,释放webview的资源
//代码初始化Webview
mWebView=new WebView(getApplicationContext());
LinearLayout linearLayout = findViewById(R.id.webview);
linearLayout.addView(mWebView);@Override
protected void onDestroy() {if( mWebView!=null) {// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再// destory()ViewParent parent = mWebView.getParent();if (parent != null) {((ViewGroup) parent).removeView(mWebView);}mWebView.stopLoading();// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错mWebView.getSettings().setJavaScriptEnabled(false);mWebView.clearHistory();mWebView.clearView();mWebView.removeAllViews();mWebView.destroy();}super.on Destroy();
}
八、资源未释放造成的内存泄漏
造成原因:对于资源的使用(如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等),若在Activity销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏
解决方案: 在Activity销毁时 及时关闭 / 注销资源
关闭资源代码如下:
// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver()// 对于 文件流File:关闭流
InputStream / OutputStream.close()// 对于数据库游标cursor:使用后关闭游标
cursor.close()// 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null
Bitmap.recycle();
Bitmap = null;// 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画
参考连接:WebView内存泄漏–解决方法小结 - 简书 (jianshu.com)
https://juejin.cn/post/6844904067534159880
相关文章:
Android常见内存泄漏场景总结
一、非静态内部类造成的内存泄漏 造成原因:非静态内部类默认会持有外部类的引用,如果内部类的生命周期超过了外部类就会造成内存泄漏。 场景:当Activity销毁后,由于内部类中存在异步耗时任务还在执行,导致Activity实…...
未来已来:Angular、React、Vue.js——前端框架的三大巨头
目录 前言 一、Angular框架 特点和优势 核心技术和应用场景 二、React框架 特点和优势 核心技术和应用场景 三、Vue.js框架 特点和优势 核心技术和应用场景 总结: 前言 在Web前端开发领域,随着技术的不断发展,出现了众多优秀的框…...
Mybatis06-动态SQL
动态SQL 1.什么是动态SQL 什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 类似JSTL标签 官网描述: MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接…...
26-LINUX--I/O复用-select
一.I/O复用概述 /O复用使得多个程序能够同时监听多个文件描述符,对提高程序的性能有很大帮助。以下情况适用于I/O复用技术: ◼ TCP 服务器同时要处理监听套接字和连接套接字。 ◼ 服务器要同时处理 TCP 请求和 UDP 请求。 ◼ 程序要同时处理多个套接…...
spring源码解析-(2)Bean的包扫描
包扫描的过程 测试代码: // 扫描指定包下的所有类 BeanDefinitionRegistry registry new SimpleBeanDefinitionRegistry(); // 扫描指定包下的所有类 ClassPathBeanDefinitionScanner scanner new ClassPathBeanDefinitionScanner(registry); scanner.scan(&quo…...
Java 数学计算 - Random类
在Java中,Random类用于生成伪随机数。这个类在java.util包中,你可以使用它来生成整数、浮点数等不同类型的随机数。以下是关于Random类的一些学习笔记和示例。 1. 创建Random对象 首先,你需要创建一个Random对象。默认情况下,如…...
Ubuntu22.04之解决:无法关机和重启问题(二百四十三)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
大学数字媒体艺术设计网页设计试题及答案,分享几个实用搜题和学习工具 #媒体#职场发展
现在读书可不像小时候,以前想要校对试题答案,都得找到对应的纸质版答案查看,而且有的还只有答案,没有解析,无法弄清楚答案的由来。但是现在不一样了,现在我们可以通过搜题软件,寻找试题的答案&a…...
【ArcGIS微课1000例】0119:TIFF与grid格式互相转换
文章目录 一、任务描述二、tiff转grid三、grid转tif四、注意事项一、任务描述 地理栅格数据常用TIFF格式和GRID格式进行存储。TIFF格式的栅格数据常以单文件形式存储,不仅存储有R、G、B三波段的像素值,还保存有地理坐标信息。GRID格式的栅格数据常以多文件的形式进行存储,且…...
B3870 [GESP202309 四级] 变长编码
[GESP202309 四级] 变长编码 题目描述 小明刚刚学习了三种整数编码方式:原码、反码、补码,并了解到计算机存储整数通常使用补码。但他总是觉得,生活中很少用到 2 31 − 1 2^{31}-1 231−1 这么大的数,生活中常用的 0 ∼ 100 0…...
WordPress网站更换域名后如何重新激活elementor
在创建WordPress网站时,我们常常需要更改域名。但是,在更换域名后,你可能会遇到一个问题:WordPress后台中的Elementor插件授权状态会显示为不匹配。这时,就需要重新激活Elementor插件的授权。下面我会详细说明如何操作…...
linux cron 执行url
linux cron 执行url 在Linux中,你可以使用curl或wget来执行URL。如果你想要定期执行这个操作,可以使用cron来设置定时任务。 以下是一个使用curl在cron中执行URL的例子: 打开终端。 输入 crontab -e 命令来编辑你的cron作业。 添加一个新…...
压缩视频在线压缩网站,压缩视频在线压缩工具软件
在数字化时代,视频成为了人们记录和分享生活的重要载体。然而,视频文件一般都非常大,这不仅占据了大量的存储空间,也给视频的传输和分享带来了不便。因此,压缩视频成为了许多人必须掌握的技能。本文将详细介绍如何压缩…...
linux经典例题编程
编写Shell脚本,计算1~100的和 首先vi 1.sh,创建一个名为1.sh的脚本,然后赋予这个脚本权限,使用命令chmod 755 1.sh,然后就可以在脚本中写程序,然后运行。 shell脚本内容 运行结果: 编写Shell脚本…...
二叉树的实现(初阶数据结构)
1.二叉树的概念及结构 1.1 概念 一棵二叉树是结点的一个有限集合,该集合: 1.或者为空 2.由一个根结点加上两棵别称为左子树和右子树的二叉树组成 从上图可以看出: 1.二叉树不存在度大于2的结点 2.二叉树的子树有左右之分,次序不能…...
C++笔试强训day41
目录 1.棋子翻转 2.宵暗的妖怪 3.过桥 1.棋子翻转 链接https://www.nowcoder.com/practice/a8c89dc768c84ec29cbf9ca065e3f6b4?tpId128&tqId33769&ru/exam/oj (简单题)对题意进行简单模拟即可: class Solution { public:int dx[…...
【JavaScript】内置对象 - 字符串对象 ⑤ ( 判断对象中是否有某个属性 | 统计字符串中每个字符出现的次数 )
文章目录 一、判断对象中是否有某个属性1、获取对象属性2、判定对象是否有某个属性 二、统计字符串中每个字符出现的次数1、算法分析2、代码示例 String 字符串对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String 一、判…...
Linux环境下测试服务器的DDR5内存性能
要在Linux环境下测试服务器的DDR5内存性能,可以采用以下几种方法和工具: ### 测试原理 内存性能测试主要关注以下几个关键指标: - **带宽**:内存每秒能传输的数据量。 - **延迟**:内存访问请求从发出到完成所需的时间…...
19、matlab信号预处理中的中值滤波(medfilt1()函数)和萨维茨基-戈雷滤波滤(sgolayfilt()函数)
1、中值滤波:medfilt1()函数 说明:一维中值滤波 1)语法 语法1:y medfilt1(x) 将输入向量x应用3阶一维中值滤波器。 语法2:y medfilt1(x,n) 将一个n阶一维中值滤波器应用于x。 语法3:y medfilt1(x,n…...
Scala 练习一 将Mysql表数据导入HBase
Scala 练习一 将Mysql表数据导入HBase 续第一篇:Java代码将Mysql表数据导入HBase表 源码仓库地址:https://gitee.com/leaf-domain/data-to-hbase 一、整体介绍二、依赖三、测试结果四、源码 一、整体介绍 HBase特质 连接HBase, 创建HBase执行对象 初始化…...
单一模型可能涌现不出超级智能,但 Agent 协作体却极有可能。
当 AI 把产品能力拉齐,注意力才是唯一的护城河 你有没有这种感觉?2025 年底,用 AI 一键生成一个完整 App 已经不是什么新闻,Vibe Coding 让普通开发者一天就能上线一个产品。可产品做出来了,下载量却像石沉大海&#x…...
从Shadertoy到Cesium:那些GLSL移植时没人告诉你的分辨率陷阱
GLSL跨平台移植中的分辨率适配陷阱与实战解决方案 当我们将Shadertoy上令人惊艳的GLSL效果移植到Cesium等三维引擎时,往往会遇到一个看似简单却影响深远的问题——分辨率适配。这个问题不仅关乎视觉效果还原度,更直接影响着色器在不同设备上的表现一致性…...
OpenClaw技能扩展:安装百川2-13B-4bits专用插件提升自动化能力
OpenClaw技能扩展:安装百川2-13B-4bits专用插件提升自动化能力 1. 为什么需要为OpenClaw安装专用插件 去年冬天,我在处理一批技术文档归档任务时,发现OpenClaw的基础能力虽然强大,但在处理特定领域内容时总有些力不从心。比如让…...
Stable Diffusion像素艺术工作站:Pixel Fashion Atelier支持LoRA在线热切换
Stable Diffusion像素艺术工作站:Pixel Fashion Atelier支持LoRA在线热切换 1. 像素时装锻造坊简介 Pixel Fashion Atelier是一款基于Stable Diffusion与Anything-v5的图像生成工作站,专为像素艺术创作而设计。与传统AI工具不同,它采用了复…...
为什么AI Coding、Skills、Agent智能体都偏爱Markdown?
为什么AI Coding、Skills、Agent智能体都偏爱Markdown? 更多问题讨论和资料获取,请关注文章最后的微信公众号 从ChatGPT的输出到GitHub Copilot的提示,从Claude的记忆存储到智能体的工作流配置——Markdown无处不在。这不是巧合,…...
寻音捉影·侠客行多场景落地:覆盖会议/媒体/司法/金融/教育五大垂直领域
寻音捉影侠客行多场景落地:覆盖会议/媒体/司法/金融/教育五大垂直领域 1. 产品核心功能解析 寻音捉影侠客行是一款基于先进语音识别技术的音频关键词检索工具,它能够像江湖中的隐士高手一样,在浩瀚的音频海洋中精准定位特定关键词。这款工具…...
AI赋能React开发:让快马智能助手帮你设计和优化复杂组件逻辑
AI赋能React开发:让快马智能助手帮你设计和优化复杂组件逻辑 最近在开发一个电商网站时,遇到了一个常见的需求:实现一个侧边栏商品筛选组件。这个组件需要包含价格区间滑块、多品牌复选框和分类下拉选择三个主要功能。刚开始觉得这个需求挺简…...
Untrunc:10倍速视频修复工具,让损坏的MP4/MOV文件起死回生
Untrunc:10倍速视频修复工具,让损坏的MP4/MOV文件起死回生 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 你是否曾经因为视频文件损坏而失去…...
springboot框架健康饮食营养管理信息系统
目录需求分析与系统设计技术栈选型与环境搭建核心功能实现数据可视化与报告生成测试与部署项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作需求分析与系统设计 明确健康饮食营养管理系统的核心需求,包括用户注册登录…...
【悬疑言情小说推荐】《血语玫瑰》
《血语玫瑰》国际标准书号:ISBN:978-986-6364-30-3 作者:追月逐花 本书地址:http://e.dangdang.com/products/1901197341.html 每个女孩都期待男友年轻英俊、家境优渥、学识出众,而 “魔鬼” 恰好符合所有条件&…...
