1. 內(nèi)存泄漏的Activity
public class MainActivity extends AppCompatActivity {
private static final int MESSAGE_TYPE1 = 10;
private Button mBtnSendMessage;
private TextView mTvShow;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_TYPE1:
mTvShow.setText("hhh");
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnSendMessage = findViewById(R.id.btn_go_second);
mTvShow = findViewById(R.id.tv_show);
mBtnSendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.what = MESSAGE_TYPE1;
// 直接發(fā)送,沒(méi)啥問(wèn)題
mHandler.sendMessage(msg);
// 延遲發(fā)送擅腰,如果Activity已經(jīng)銷毀莹弊,內(nèi)存泄漏
mHandler.sendMessageDelayed(msg,1000*60*5);
}
});
}
}
分析:Main線程中 有一個(gè)Message 持有者Handler的引用涤久,而且Handler??持有外部類MainActivity的應(yīng)用,所以產(chǎn)生了內(nèi)存泄漏忍弛。MainActivity沒(méi)有被及時(shí)的釋放掉响迂。
LeakCanary的內(nèi)存泄漏截圖
2. 無(wú)內(nèi)存泄漏的Handler
public class MainActivity extends AppCompatActivity {
private static final int MESSAGE_TYPE1 = 10;
private Button mBtnSendMessage;
private TextView mTvShow;
private SuperHandler mHandler = new SuperHandler(this);
private static class SuperHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
private SuperHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_TYPE1: {
MainActivity activity = mActivity.get();
if(activity != null) {
activity.setTvShowText("hhh");
}
}
}
// end handleMessage
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnSendMessage = findViewById(R.id.btn_go_second);
mTvShow = findViewById(R.id.tv_show);
mBtnSendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.what = MESSAGE_TYPE1;
// mHandler.sendMessage(msg);
mHandler.sendMessageDelayed(msg,1000*60*5);
}
});
}
public void setTvShowText(String text) {
mTvShow.setText(text);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 移除所有的消息隊(duì)列
mHandler.removeCallbacksAndMessages(null);
}
}
分析:和原來(lái)的不同之處在于這里采用了靜態(tài)內(nèi)部類的形式 來(lái)實(shí)現(xiàn)了一個(gè)SuperHandler,這樣SuperHandler就不會(huì)持有MainActivity的引用细疚。在Activity的OnDestroy結(jié)束之后蔗彤,弱引用mActivity的值就get出來(lái)就為空了。
OnDestroy中移除掉消息池中的消息疯兼,完事
繼續(xù)看下Handler的removeCallbacksAndMessages的源碼我們可以發(fā)現(xiàn)
Handler 關(guān)聯(lián)綁定一個(gè)Queue然遏,通過(guò)調(diào)用queue.removeCallbacksAndMessages移除所有target為當(dāng)前Handler的message。
void removeCallbacksAndMessages(Handler h, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
// 目標(biāo)為當(dāng)前對(duì)象镇防,則移除
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
最后稍微理一下Handler啦鸣、Looper、Message的關(guān)系
- Handler:內(nèi)部包含Looper中的Queue来氧,以及handleMessage的方法(沒(méi)有設(shè)置任何回調(diào)接口的情況下才會(huì)使用)
- Message:一般通過(guò)obtain()方法獲得一個(gè)Message诫给,消息池中如果有消息可以復(fù)用,沒(méi)有就會(huì)新建啦扬。Message.target指向的是一個(gè)Handler
- Looper:持有消息隊(duì)列中狂,會(huì)調(diào)用Handler的dispatchMessage方法(有回調(diào)用回調(diào),沒(méi)有則調(diào)用handleMessage方法)扑毡,并且這個(gè)Handler是唯一的胃榕,因?yàn)镸essage中有target屬性指向Handler
如有錯(cuò)誤歡迎指正,謝謝瞄摊!