Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
handler.sendEmptyMessage(0);
當(dāng)你如此定義一個(gè)handler的時(shí)候矗愧,系統(tǒng)會(huì)提示你,可以會(huì)產(chǎn)生內(nèi)存泄漏郑原,那么為什么會(huì)產(chǎn)品內(nèi)存泄漏唉韭,如何避免。
先來分析一下為什么會(huì)產(chǎn)品內(nèi)存泄漏犯犁,首先上面的Handler是一個(gè)內(nèi)部類属愤,內(nèi)部類會(huì)持有外部類的引用,所以Handler持有了Activity的引用酸役,sendEmptyMessage的時(shí)候會(huì)創(chuàng)建一個(gè)Message
對(duì)象住诸,而Message持有Handler的引用,然后Message會(huì)被添加進(jìn)入MessageQueue涣澡,Looper執(zhí)行l(wèi)oop之后會(huì)循環(huán)從MessageQueue取出Message消費(fèi)掉贱呐,MainLooper是在AvtivityThread里面初始化,且不能停止入桂。所以一個(gè)引用連就分析出來了奄薇。
Activity-Handler-Message-MessageQueue-Looper。當(dāng)Activity創(chuàng)建了Handler且Activity結(jié)束的時(shí)候抗愁,Message還在MessageQueue里面的話馁蒂,就會(huì)內(nèi)存泄漏。
什么是內(nèi)存泄漏驹愚,我的理解就是远搪,當(dāng)分配了內(nèi)存空間,卻沒有回收就是內(nèi)存泄漏了逢捺,JAVA的回收都由GC去完成谁鳍,垃圾回收機(jī)制會(huì)不停的掃描一個(gè)對(duì)象是或否可以被回收掉,經(jīng)過掃描標(biāo)記回收等操作,那怎么判斷一個(gè)對(duì)象是否可以被回收呢倘潜?JAVA采用了可達(dá)性分析才判斷一個(gè)對(duì)象是否可以被回收绷柒。
用一個(gè)Activity舉例,當(dāng)Activity被finish之后涮因,就不應(yīng)該在有其他對(duì)象保持對(duì)Activity的引用废睦,否則就會(huì)造成Activity不能被回收,從而造成內(nèi)存泄漏养泡,也就是上面分析Handler引起內(nèi)存泄漏的原因嗜湃。總結(jié)起來就是一句話澜掩,生命周期短的對(duì)象引用了生命周期長(zhǎng)的對(duì)象购披,從而造成生命周期短的對(duì)象不能正常回收肩榕,從而造成了內(nèi)存泄漏刚陡。
生命周期長(zhǎng)的對(duì)象比方說靜態(tài)對(duì)象,常駐線程株汉,單例等筐乳,使用長(zhǎng)生命周期對(duì)象時(shí)一定要注意內(nèi)存泄漏。
在回到上面的Handler內(nèi)存泄漏的問題乔妈,其實(shí)只要切斷引用連蝙云,內(nèi)存泄漏就解決了,可以在Activirty結(jié)束的時(shí)候褒翰,如果有未執(zhí)行完的Message可以remove掉贮懈,android studio上也提示了另外一種解決辦法,靜態(tài)Handler+弱引用优训。
說到弱引用朵你,就要說到JAVA幾種常用的引用方式,強(qiáng)揣非、軟抡医、弱、虛早敬。上面說的可達(dá)性分析等都是強(qiáng)引用忌傻,而軟件引用在系統(tǒng)內(nèi)存不足時(shí)會(huì)被強(qiáng)制釋放掉,需注意從2.3開始搞监,android加強(qiáng)了軟引用的回收水孩。弱引用的回收比軟引用來的更快,如果垃圾回收時(shí)琐驴,只有弱引用對(duì)此對(duì)象保持引用則會(huì)被回收俘种。所以靜態(tài)Handler+弱引用秤标,靜態(tài)保證了不持有當(dāng)前Activity對(duì)象,而弱引用拿到了當(dāng)前Activity的句柄宙刘。所以只要注意對(duì)象的生命周期還有引用方式苍姜,內(nèi)存泄漏就自然解決了。