Handler中有可能引起的内存泄漏

上一篇文章中使用Handler的方式是这样的:

public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//实例化Handler,重写回调方法
Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        if (msg.what == 0) {
            /*sendMessage方法更新UI的操作必须在handler的handleMessage回调中完成*/
            mTextView.setText(new_str);
        }
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
        @Override
        public void run() {
            new_str = "sendMessage更新UI";
            /*sendMessage方法解决UI更新发送消息给handler(主线程中的handler)*/
            mHandler.sendEmptyMessage(0);
        }
    }).start();
}             

咋一看ok,其实有潜在的隐患,有可能会引发内存泄漏,原因是由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏 。
这里我们需要引入弱引用,规范的书写方法如下:

public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//实例化Handler,使用静态内部类,使得Handler仅仅持有Activity的弱引用
Handler mHandler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
        @Override
        public void run() {
            new_str = "sendMessage更新UI";
            /*sendMessage方法解决UI更新发送消息给handler(主线程中的handler)*/
            mHandler.sendEmptyMessage(0);
        }
    }).start();
}       
static class MyHandler extends Handler{
  WeakReference<Activity> mActivityReference;
  MyHandler(Activity activity) { 
      mActivityReference= new WeakReference<Activity>(activity);
 } 
@Override
public void  handleMessage(Message msg) { 
 final Activity activity = mActivityReference.get(); 
 if (activity != null) {   mTextView.setText(new_str);
   } 
  }
 }  

总结

避免Handler引发的内存泄漏:静态内部类不会持有对外部类的引用。所以,使用静态内部类便可以避免泄漏。另外,如果想要在handler内部去调用所在的外部类Activity,那么可以在handler内部使用弱引用的方式指向所在Activity。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容