在Android的開發(fā)過程中,Handler經(jīng)常被使用到闷哆,我們可以通過它的handlerMessage方法來(lái)處理一些異步返回的結(jié)果。常用到如下代碼:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case LOADDBDATA:
// do something when msg.what=0x01
// ...
// ...
break;
default:
break;
}
}
};
這樣寫可以實(shí)現(xiàn)功能礁遵,但是在會(huì)受到編譯器的一個(gè)警告
這段警告的大意是:
內(nèi)容來(lái)自:http://blog.csdn.net/atangsir/article/details/48226789
1.當(dāng)這個(gè)App啟動(dòng)的時(shí)候,會(huì)自動(dòng)創(chuàng)建一個(gè)供應(yīng)用主線程使用的Looper實(shí)例采记。Looper負(fù)責(zé)管理MessageQueue和Message對(duì)象佣耐,讀取到MessageQueue中的Message之后就會(huì)采用sendMessage的方式把消息發(fā)送給對(duì)應(yīng)的Handler來(lái)處理,Looper接收到一條一條的消息后逐一進(jìn)行處理唧龄,所以主線程中的Looper和App的生命周期一樣長(zhǎng)兼砖。
2.當(dāng)一個(gè)Handler在主線程進(jìn)行了初始化之后,我們發(fā)送一個(gè)target為這個(gè)Handler的消息到Looper處理的消息隊(duì)列時(shí)既棺,實(shí)際上已經(jīng)發(fā)送的消息包含了一個(gè)Handler實(shí)例的引用讽挟,只有這樣Looper在處理到這條消息時(shí)才可以調(diào)用 Handler#handleMessage(Message)完成消息的正確處理。
3.在Java中丸冕,非靜態(tài)的內(nèi)部類和匿名內(nèi)部類都會(huì)隱式地持有其外部類的引用耽梅。靜態(tài)的內(nèi)部類不會(huì)持有外部類的引用。
個(gè)人覺得大意就是在:上述方式是將handler作為一個(gè)匿名內(nèi)部類使用的胖烛,因?yàn)閖ava的設(shè)計(jì)眼姐,匿名內(nèi)部類會(huì)持有外部類的引用。且Handler 屬于 TLS(Thread Local Storage) 變量, 生命周期和 Activity 是不一致的佩番。假如我們通過postDelay延時(shí)發(fā)送消息众旗,通知HandlerMessage方法做某些事情,并且在發(fā)送消息后finish掉頁(yè)面趟畏。這時(shí)因?yàn)槟涿麅?nèi)部類持有外部類的引用(既Activtiy的引用)贡歧,而activity已經(jīng)被finish掉了,此時(shí)GC回收垃圾----既不必要的對(duì)象時(shí)會(huì)發(fā)現(xiàn)activity的引用還被其他人持有赋秀,因?yàn)閔andler是一個(gè)TLS對(duì)象利朵,它并沒有被finish掉,這樣就造成了內(nèi)存的溢出沃琅。
解決方式:構(gòu)建一個(gè)靜態(tài)內(nèi)部類繼承Handler哗咆,當(dāng)聲明一個(gè)事物是static時(shí),就意味著這個(gè)域或方法不會(huì)與包含它的那個(gè)類的任何對(duì)象的實(shí)例關(guān)聯(lián)在一起益眉。在Activity中不要使用非靜態(tài)內(nèi)部類
static class MyHandler extends Handler {
WeakReference<LauncherActivity> actReference;
MyHandler(LauncherActivity launcherActivity) {
actReference =new WeakReference<LauncherActivity(launcherActivity);
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
LauncherActivity activity = actReference.get();
switch (msg.what) {
case Launcher2Login:
Intent intent = new Intent(activity, LoginActivity.class);
activity.startActivity(intent);
activity.finish();
break;
}
}
}
這里使用了弱引用來(lái)持有Activity對(duì)象晌柬,可以參考blog---http://3287316.blog.51cto.com/3277316/1335286