• 老李分享:Android性能优化之内存泄漏2


    这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏,所以另外一种做法为:

    public class MainActivity extends AppCompatActivity {

        private MyHandler mHandler = new MyHandler(this);

        private TextView mTextView ;

        private static class MyHandler extends Handler {

            private WeakReference<Context> reference;

            public MyHandler(Context context) {

                reference = new WeakReference<>(context);

            }

            @Override

            public void handleMessage(Message msg) {

                MainActivity activity = (MainActivity) reference.get();

                if(activity != null){

                    activity.mTextView.setText("");

                }

            }

        }

     

        @Override

        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            mTextView = (TextView)findViewById(R.id.textview);

            loadData();

        }

     

        private void loadData() {

            //...request

            Message message = Message.obtain();

            mHandler.sendMessage(message);

        }

    }

    创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用,这样在回收时也可以回收Handler持有的对象,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息,更准确的做法如下:

    public class MainActivity extends AppCompatActivity {

        private MyHandler mHandler = new MyHandler(this);

        private TextView mTextView ;

        private static class MyHandler extends Handler {

            private WeakReference<Context> reference;

            public MyHandler(Context context) {

                reference = new WeakReference<>(context);

            }

            @Override

            public void handleMessage(Message msg) {

                MainActivity activity = (MainActivity) reference.get();

                if(activity != null){

                    activity.mTextView.setText("");

                }

            }

        }

     

        @Override

        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            mTextView = (TextView)findViewById(R.id.textview);

            loadData();

        }

     

        private void loadData() {

            //...request

            Message message = Message.obtain();

            mHandler.sendMessage(message);

        }

     

        @Override

        protected void onDestroy() {

            super.onDestroy();

            mHandler.removeCallbacksAndMessages(null);

        }

    }

    使用mHandler.removeCallbacksAndMessages(null);是移除消息队列中所有消息和所有的Runnable。当然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();来移除指定的Runnable和Message。

  • 相关阅读:
    mysql基本命令(转)
    查找大文件
    vim/vi 复制,删除,粘贴,查找,替换
    redhat 6用yum方式安装nginx
    解决yum安装时 Cannot retrieve repository metadata (repomd.xml) for repository
    RHEL6解决无法使用YUM源问题(转)
    Linux 信号概念
    Linux 进程通信(共享内存区)
    Linux 进程通信(有名管道)
    Linux 进程通信(无名管道)
  • 原文地址:https://www.cnblogs.com/poptest/p/4995345.html
Copyright © 2020-2023  润新知