Android Handler 内存泄漏问题
16lz
2021-01-23
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 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 设置静态wifi地址
- Android中图形参数及图形内存信息获取
- Android读取设备内存大小
- Memory Analyzer(MAT)打开android eclipse Dump内存文件出现 Unkno
- Android 获得sdcard大小与内存大小工具类
- Android图片压缩及内存缓存
- 「抄底 Android 内存优化 3」 —— JVM 内存管理
- android 绘制折线图(AChartEngine)Linechart静态的
- android中 代码实现截图功能(静态+动态视频)