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程序开发中.当一个对象已经不须要再使用了,本该被回收时.而另外一个正在使用的对象持有它的引用从而导致它不能被回收.这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了. ...
随机推荐
- 附录3:RMA算法原理
RMA算法分三步: 一.背景校正(没精力写了) 二.归一化(没精力写了) 三.计算表达值 假设有5张芯片,这些芯片的某个探针组包含5个探针,它们的表达值如下: GeneChip 4 8 6 9 7 3 ...
- 面试之什么是java虚拟机
java虚拟机体系结构 方法区 堆 java虚拟机栈 本地方法栈 方法区 java虚拟机编译的class文件中二进制数据类型解析数据存在方法区中 是所有线程共享 和存在数据的线程安全问题 当二个线程使 ...
- java构造方法的注意事项总结
构造方法细节总结~~~~~ 1:首先要了解为什么需要构造方法,,,类中有太多的属性,每次给属性赋值时非常麻烦:编码量大,无法重用给属性赋值的代码.. 2:什么是构造方法呢? 构造方法负责初始化类中的实 ...
- MySQL存储引擎MyISAM和InnoDB有哪些区别?
一.MyISAM和InnoDB的区别有哪些? 1.InnoDB支持事务,MyISAM不支持.对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在be ...
- 104、验证Swarm数据持久性 (Swarm11)
参考https://www.cnblogs.com/CloudMan6/p/8016994.html 上一节我们成功将 nfs 的volume挂载到 Service上,本节验证 Failover时 ...
- Nginx配置,请求到tomcat中
一.web服务器分为两类 1.web服务器 1)Apache服务器 2)Nginx 3)IIS 2.web 应用服务器 1)tomcat 2)resin 3)jetty 区分:web服务器不能解析js ...
- pamamiko的学习笔记
pamamiko的学习笔记 Paramiko包含两个核心组件,一个为SSHClient类,另一个为SFTPClient类, 一,paramiko的连接有两种方式,一种是通过paramiko.SSHCl ...
- springmvc视图文件的保护
可以将视图文件,包含视图文件的目录放在WEB-INF下,WEB-INF是受保护的,放在该目录下,就只能在代码中访问到了view文件了,用户无法通过浏览器直接输入地址访问.
- 双向链表/list
双向链表结构如下 双向链表结构中元素在内存中不是紧邻空间,而是每个元素中存放上一个元素和后一个元素的地址 第一个元素称为头(head)元素,前连接(前置指针域)为nil 最后一个元素称为尾(foot) ...
- shell更改xml中的指定值
sed -i 's;<id>.*<\/id>;<id>新内容<\/id>;g' your.xml