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

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

This Handler class should be static or leaks might occur

例如这样的代码:

1
2
3
4
5
6
7
8
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应声明为静态内部类:

1
2
3
4
5
6
7
public class MainActivity extends Activity {

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

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

1
2
3
4
5
6
7
8
9
10
11
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中还要多一步获取与判断:

1
2
3
4
5
6
@Override
public void handleMessage(Message msg) {
if (activity.get() != null) {
activity.get().someMethod();
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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();
}
}
}
}

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :