zoukankan      html  css  js  c++  java
  • 老李分享: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。

  • 相关阅读:
    Eclipse 修改编码方式
    mybits like查询写法
    Cannot convert value '0000-00-00 00:00:00' TIMESTAMP
    Homebrew简介和基本使用
    linux命令学习之:vim
    log4j配置详解
    log4j日志配置(按天/按日)
    Linux下tar.gz、tar、bz2、zip等解压缩、压缩命令小结(转)
    Linux挂载磁盘
    linux命令学习之:echo
  • 原文地址:https://www.cnblogs.com/poptest/p/4995345.html
Copyright © 2011-2022 走看看