Android Handler 内存泄漏问题

Posted ly570

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 内存泄漏问题

Android Weak Handler:可以避免内存泄漏的Handler库

android中handler使用应该注意的问题(解决由handler引起的OOM内存泄漏)

Android Socket、AsyncTask、Handler 内存泄漏

Android开发常见的Activity中内存泄漏及解决办法

Android面试每日一题: Handler 如何有效地避免内存泄漏问题