Android自定义Handler使用静态内部类避免内存泄漏

在Activity中声明Handler类时,Android Studio会提示警告:

This Handler class should be static or leaks might occur

例如这样的代码:

public class MainActivity extends Activity {

    // This Handler class should be static or leaks might occur
    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {  }
    }
}

因为如果Handler使用UI线程来做消息序列的处理,那么可能会导致Activity类无法被回收,继而引发内存泄漏。

通俗的讲,耗时内部类引用外部类,可能导致外部类无法回收

因此按照警告中的提示,Handler应声明为静态内部类:

public class MainActivity extends Activity {

    static class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {  }
    }
}

声明为静态类以后,Handler就没有了Activity的引用,无法直接引用其变量或方法了,因此我们在这里使用弱引用WeakReference来解决这个问题:

static class MyHandler extends Handler {

    WeakReference<MainActivity> activity;

    public DownloadHandler(MainActivity mainActivity) {
        activity = new WeakReference<MainActivity>(mainActivity);
    }

    @Override
    public void handleMessage(Message msg) {  }
}

WeakReference可以尽早地被GC回收掉,因此可以防止内存泄漏。由于这里的activity变量实际不是MainActivity类型的,因此在handleMessage中还要多一步获取与判断:

@Override
public void handleMessage(Message msg) {
    if (activity.get() != null) {
        activity.get().someMethod();
    }
}

当然每次这样调用比较麻烦,可以将WeakReference声明初始化在MainActivity中,在Handler初始化时直接传入:

public class MainActivity extends Activity {

    WeakReference<MainActivity> activity;
    MyHandler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        activity = new WeakReference<MainActivity>(mainActivity);
        mHandler = new MyHandler(activity);
    }

    class MyHandler extends Handler {
        private MainActivity activity;

        public MyHandler(WeakReference<MainActivity> ref) {
            activity = ref.get();
        }

        @Override
        public void handleMessage(Message msg) {
            if(activity != null) {
                activity.someMethod();
            }
        }
    }
}
上一篇 Android NDK 开发使用 ANDROID_LOG 日志库
下一篇 Android反编译
目录
文章列表
1 Flutter Widget之GridView
Flutter Widget之GridView
2
Android申请电源锁与释放电源锁
Android申请电源锁与释放电源锁
3
CentOS下部署Jenkins
CentOS下部署Jenkins
4
Docker容器启动报错:Error response from daemon OCI runtime create failed container_linux.go
Docker容器启动报错:Error response from daemon OCI runtime create failed container_linux.go
5
TestNG测试结果报告
TestNG测试结果报告
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。