上一篇文章中使用Handler的方式是这样的:
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//实例化Handler,重写回调方法
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
/*sendMessage方法更新UI的操作必须在handler的handleMessage回调中完成*/
mTextView.setText(new_str);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
new_str = "sendMessage更新UI";
/*sendMessage方法解决UI更新发送消息给handler(主线程中的handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
咋一看ok,其实有潜在的隐患,有可能会引发内存泄漏,原因是由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏 。
这里我们需要引入弱引用,规范的书写方法如下:
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//实例化Handler,使用静态内部类,使得Handler仅仅持有Activity的弱引用
Handler mHandler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
new_str = "sendMessage更新UI";
/*sendMessage方法解决UI更新发送消息给handler(主线程中的handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
static class MyHandler extends Handler{
WeakReference<Activity> mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) { mTextView.setText(new_str);
}
}
}
总结
避免Handler引发的内存泄漏:静态内部类不会持有对外部类的引用。所以,使用静态内部类便可以避免泄漏。另外,如果想要在handler内部去调用所在的外部类Activity,那么可以在handler内部使用弱引用的方式指向所在Activity。