上一篇文章中使用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更新發(fā)送消息給handler(主線程中的handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
咋一看ok,其實有潛在的隱患乾忱,有可能會引發(fā)內存泄漏,原因是由于mHandler是Handler的非靜態(tài)匿名內部類的實例京髓,所以它持有外部類Activity的引用斩启,我們知道消息隊列是在一個Looper線程中不斷輪詢處理消息,那么當這個Activity退出時消息隊列中還有未處理的消息或者正在處理消息芳誓,而消息隊列中的Message持有mHandler實例的引用余舶,mHandler又持有Activity的引用,所以導致該Activity的內存資源無法及時回收锹淌,引發(fā)內存泄漏 匿值。
這里我們需要引入弱引用,規(guī)范的書寫方法如下:
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//實例化Handler赂摆,使用靜態(tài)內部類挟憔,使得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更新發(fā)送消息給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引發(fā)的內存泄漏:靜態(tài)內部類不會持有對外部類的引用钟些。所以,使用靜態(tài)內部類便可以避免泄漏绊谭。另外政恍,如果想要在handler內部去調用所在的外部類Activity,那么可以在handler內部使用弱引用的方式指向所在Activity达传。