美文网首页
Android Handler内存泄漏问题

Android Handler内存泄漏问题

作者: 静水红阳 | 来源:发表于2020-07-27 15:58 被阅读0次

问题

在Java中非静态内部类或者匿名内部类都是默认持有外部类的引用的。
当我们使用handler时,如果我们按照下述写法,则会提示一个错误:

        var hh = object : Handler() {
            override fun handleMessage(msg: Message?) {
                super.handleMessage(msg)
            }
        }

则会看到编译器提示我们一个警告,主要意思如下:

由于handler定义为内部类,可能会阻止GC。如果handler的Looper或MessageQueue 非主线程,那么没有问题。如果handler的Looper或MessageQueue 在主线程,那么需要按如下定义:定义handler为静态内部类,当你实例化handler的时候,传入一个外部类的弱引用,以便通过弱引用使用外部类的所有成员

原因

handler发送的消息在当前的handler的消息队列中,如果此时activity finish掉落,那么消息队列的消息依旧会由handler进行处理,如果此时handler为非静态内部类,持有外部类Activity的引用,这样GC垃圾回收机制进行回收时发现这个Activity还有引用存在,因而就不会去回收这个Activity,进而导致activity泄漏。
非静态内部类持有了外部类的对象。

解决办法

  1. 将handler定义为static。

静态内部类不持有外部类的引用,所以使用静态的handler不会导致activity的泄漏。

  1. 使用WeakReference包裹外部类的对象。

静态内部类中需要使用外部类的成员,弱引用不会导致内存泄漏。

示例代码

public class MainActivity extends AppCompatActivity {

    TextView mTextView;

    MyHandler mMyHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.tv_handler);
        mMyHandler = new MyHandler(MainActivity.this);
        doInBackground();
    }

    private static class MyHandler extends Handler {
        private WeakReference<MainActivity> mWeakReference;

        public MyHandler(MainActivity activity) {
            mWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity mainActivity = mWeakReference.get();
            switch (msg.what) {
                case 1:
                    if (mainActivity != null) {
                        mainActivity.mTextView.setText(msg.obj + "");
                    }
                    break;
                default:
                    break;
            }
        }
    }

    private void doInBackground() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //模拟耗时操作
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //耗时操作完成,发送消息给UI线程
                Message msg = Message.obtain();
                msg.what = 1;
                msg.obj = "更新UI";
                mMyHandler.sendMessage(msg);
            }
        }).start();
    }

}

相关文章

  • (转载自diycode)2017 Android 面试题分享整理

    Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析及解决 An...

  • Android 基础

    1、Android布局 2、Android内存泄漏总结 3 、Handler内存泄漏分析及解决 4...

  • java基础

    Handler怎样防止内存泄漏 handler引起内存泄漏的原因:由于handler的写法问题,如果handler...

  • 性能优化与保活

    ------内存泄漏优化------Android 内存优化你的 Handler 内存泄露 了吗?Android卡...

  • android学习资料

    第一部分: Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析...

  • Android学习之旅

    1.Android基础知识2.Android内存泄漏总结3.Handler内存泄漏分析及解决4.Android性能...

  • Android知识体系总结

    第一部分:Android(安卓)Android基础知识Android内存泄漏总结Handler内存泄漏分析及解决H...

  • app性能优化 - 避免内存泄漏2

    提出问题: Handler造成的内存泄漏问题Handler之所以造成内存泄漏是因为在activity销毁的时候,H...

  • Android 消息机制 你了解多少

    级别:★★☆☆☆标签:「Handler」「Android」「消息机制」「内存泄漏」作者: Zoyp晨[https:...

  • Android Handler 内存泄漏问题

    1. 内存泄漏的Activity 分析:Main线程中 有一个Message 持有者Handler的引用,而且Ha...

网友评论

      本文标题:Android Handler内存泄漏问题

      本文链接:https://www.haomeiwen.com/subject/udwzlktx.html