Android Handler 内存泄漏问题
1. 问题
先看以下代码:
第一种写法:
public class MainActivity extends AppCompatActivity {
...
...
...
private class MyHandler extends Handler {
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == 10086) {
mTv.setText(String.valueOf(msg.arg1));
}
}
}
...
...
...
}
第二种写法:
public class MainActivity extends AppCompatActivity {
...
...
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
...
...
...
}
}
?
对于 Handler?这两种创建方式,Android Studio 虽然不会报错,但是会有提醒:
意思是 Handler 类必须为静态,否则会造成泄漏。
2.原因
非静态内部类和匿名内部类会持有外部类的引用。在 Handler 消息队列还有正在处理或者未处理消息时候,消息队列中的 Message 持有 Handler 实例的引用。由于Handler 为非静态内部类或者匿名内部类时候,又持有外部类的引用,也就是持有外部 MainActivity 实例。而这样的引用关系会一直保持。
此时,如果销毁外部类(MainActivity 实例),由于存在引用关系,垃圾回收机制中,外部类(MainActivity 实例)就无法被回收,从而造成内存泄漏。
内存泄漏在 Android 开发是一个严重的问题,系统给每个应用分配的内存是固定的,一旦发生了内存泄漏,就会导致应用的可用内存越来越小,最终导致 OOM 的发生。
3.解决方法
方法1:静态内部类+弱引用
将 Handler 的子类设置成静态内部类,静态内部类不再默认持有外部类的引用,从而使得引用关系不再存在。同时,再加上使用弱引用(WeakReference)持有Activity实例,当发生GC时候,一旦发现了只具有弱引用的对象,不管当前内存是否足够,都会回收它的内存。
public class MainActivity extends AppCompatActivity {
...
...
...
private static class MyHandler extends Handler {
WeakReference<Activity> reference;
public MyHandler(Activity activity) {
reference = new WeakReference<>(activity);
}
@Override
public void handleMessage(@NonNull Message msg) {
if(null!=reference)
{
MainActivity activity = (MainActivity) reference.get();
if(null!=activity) {
if (msg.what == 10086) {
activity.mTv.setText(String.valueOf(msg.arg1));
}
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler=new MyHandler(this);
...
...
...
}
}
?2. 及时清除消息
当外部类(Activity)生命周期结束时候,清除 Handler 消息队列里的所有消息。
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
Android Handler 内存泄漏问题的更多相关文章
- Android Handler 内存泄漏,文末消息机制的小总结
1. 内存泄漏的Activity public class MainActivity extends AppCompatActivity { private static final int MESS ...
- 利用Android Studio、MAT对Android进行内存泄漏检测
利用Android Studio.MAT对Android进行内存泄漏检测 Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的c ...
- Android防止内存泄漏以及MAT的使用
Android发生内存泄漏最普遍的一种情况就是长期保持对Context,特别是Activity的引用,使得Activity无法被销毁.这也就意味着Activity中所有的成员变量也没办法销毁.本文仅介 ...
- android 常见内存泄漏原因及解决办法
android常见内存泄漏主要有以下几类: 一.Handler 引起的内存泄漏. 在Android开发中,我们经常会使用Handler来控制主线程UI程序的界面变化,使用非常简单方便,但是稍不注意,很 ...
- android性能测试内存泄漏
1.什么是内存泄漏? 适用于该系统的内存使用内存泄漏,未回复(释放),该内存可以没有事业,也不能被其他人使用使用自己. 2.出有什么差别? 内存泄漏是分配出去的内存无法回收. 内存 ...
- [原理] Android Native内存泄漏检测原理解析
转载请注明出处:https://www.cnblogs.com/zzcperf/articles/11615655.html 上一篇文章列举了不同版本Android OS内存泄漏的检测操作(传送门), ...
- Android App 内存泄漏Handler
Android App 内存泄露之Handler Handler也是造成内存泄露的一个重要的源头,主要Handler属于TLS(Thread Local Storage)变量,生命周期和Activit ...
- [轉]Android的内存泄漏和调试
一. Android的内存机制 Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的 ...
- Android 常见内存泄漏的解决方式
在Android程序开发中.当一个对象已经不须要再使用了,本该被回收时.而另外一个正在使用的对象持有它的引用从而导致它不能被回收.这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了. ...
随机推荐
- docopt 安装及基本应用
什么是 docopt docopt是一种python 编写的命令行执行脚本的交互语言. 它是一种语言! 它是一种语言! 它是一种语言! 使用这种语言可以在自己的脚本中,添加一些规则限制,这样脚本在执行 ...
- org.apache.shiro.realm.AuthorizingRealm - No cache or cacheManager properties have been set. Authorization cache cannot be obtained.
项目中用spring shiro来处理权限的问题,但是启动的时候会打印如下日志 org.apache.shiro.realm.AuthorizingRealm - No cache or cacheM ...
- spring boot jpa @PreUpdate结合@DynamicUpdate使用的局限性
通常给实体添加audit审计字段是一种常用的重构方法,如下: @Embeddable @Setter @Getter @ToString public class Audit { /** * 操作人 ...
- 1.SpringBoot整合Mybatis(CRUD的实现)
准备工具:IDEA jdk1.8 Navicat for MySQL Postman 一.新建Project 选择依赖:mybatis Web Mysql JDBC 项目结构 pom依赖: & ...
- NFS pv部署
一.部署nfs服务端: 可以选择kubernetes_cluster内的任意的node去做为nfs服务端,部署节点也可以.我选择的是部署节点去做为nfs服务端. (1)部署节点安装nfs服务软件包: ...
- Python基础编程:字符编码、数据类型、列表
目录: python简介 字符编码介绍 数据类型 一.Python简介 Python的创始人为Guido van Rossum.1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心 ...
- html和css牛刀小试
html和css网上教程很多,这里我也给大家一个网址:https://www.cnblogs.com/majj/ 今天心血来潮就模仿着小米的官网写了部分代码,效果图如下:(本人故意加了个华为广告栏在最 ...
- LIS 普及题
题意 给你一个长度为 \(n\) 的序列 \(a\). 问是否存在一个长度为 \(L\) 的上升子序列,即存在 \(\{x_1,x_2,...,x_L\}(x_1\lt x_2\lt ...\lt x ...
- php和redis实现消息队列
php+redis消息队列是php+mysql性能不足时的一个中间间处理方案.通过这个中间的处理,保证的数据的可用性和准确性.用于服务器瞬间请求大,数据库压力大的情况.如并发量大导致的超卖.并发量大导 ...
- msvsmon.exe xp下不能运行
远程调试 xp 下不能执行 vs2013 远程调试器 xp下不能运行 vs2010 远程调试器 xp下可以运行