handler 内存泄露小记

59 阅读1分钟

内存问题

  1. 内存泄露 (对象不被回收,一直占据着内存,反复内存泄露将引发内存溢出)
  2. 内存溢出 OOM(内存不够用)

垃圾回收

如何判定是垃圾

  1. 引用计数法(可能存在互相引用无法被回收)
  2. 可达性分析(从各个GCROOT 出发,如果无法被找到的对象就会被回收)

handler 内存泄露

image.png 此处 handler 对象为内部类,非静态内部类和匿名内部类能够调用外部类的属性,因此该内部类实际上持有外部类的引用。此时如果 Activity 生命周期结束需要被回收,但是handler这个匿名内部类仍然持有Activity引用导致回收失败

解决方式

  1. 定义静态内部类 handler,同时持有外部类的弱引用, 弱引用不会阻止 gc 回收。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static_handler);

        initView();
    }

    private void initView() {
        mStateTv = findViewById(R.id.tv_state);
    }

    private static class MyHandler extends Handler {
        private final WeakReference<StaticHandlerActivity> mActivity;

        public MyHandler(StaticHandlerActivity activity) {
            mActivity = new WeakReference<StaticHandlerActivity>(activity); //获取弱引用Activity对象
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            if (mActivity.get() != null) {
                //TODO
                //利用弱引用来获取UI控件,不会对回收造成影响
                mActivity.get().mStateTv.setText("state change");
                
                //如果直接new Activity()来获取Activity属于强引用,依然会造成内存泄漏
                //new StaticHandlerActivity().mStateTv.setText("state change"); 
            }
        }
    }
}