前言
內(nèi)存泄漏其實(shí)是用戶無(wú)感的薪夕,可能一次或幾次的泄漏危害可以忽略,但內(nèi)存泄漏堆積后赫悄,會(huì)影響app的性能原献,嚴(yán)重可能會(huì)導(dǎo)致oom,內(nèi)存溢出涩蜘。
小伙伴們?cè)趯?shí)際開發(fā)中嚼贡,要防止內(nèi)存泄漏的產(chǎn)生。大家可以通過(guò)內(nèi)存檢測(cè)工具同诫,來(lái)查看你的項(xiàng)目是否有內(nèi)存泄漏的產(chǎn)生粤策。
防止內(nèi)存泄漏的方法有許多,這里只列舉了handler與Asyntask防止內(nèi)存的產(chǎn)生误窖,因?yàn)楸容^實(shí)用叮盘,未了解的小伙伴可以收藏一下。
一霹俺、舉個(gè)栗子
這是某內(nèi)存檢測(cè)工具柔吼,是handler引起的內(nèi)存泄漏錯(cuò)誤信息
In com.ophone.reader.ui:6.8.3:118.
* com.cmread.bplusc.reader.ui.share.ShareToFXActivity has leaked:
* GC ROOT static com.cmread.bplusc.httpservice.http.HttpMessageQueue.mSelf
* references com.cmread.bplusc.httpservice.http.HttpMessageQueue.mCallback
* references com.cmread.bplusc.httpservice.http.HttpQueueCallback.mICallBack
* references com.cmread.bplusc.presenter.AbsPresenter$1.this$0 (anonymous class implements com.cmread.bplusc.httpservice.aidl.ICallBack)
* references com.cmread.bplusc.presenter.GetShareLinkPresenter.mUIHandler
* references com.cmread.bplusc.reader.ui.share.ShareToFXActivity$1.this$0 (anonymous class extends android.os.Handler)
* leaks com.cmread.bplusc.reader.ui.share.ShareToFXActivity instance
從上述日志中可以得出,ShareToFxActivity有泄漏的產(chǎn)生丙唧,這里的mSelf指的就是ShareToFxActivity愈魏,因?yàn)樵谄渌胤接衜Self的引用,從而導(dǎo)致改Activity在finish的時(shí)候無(wú)法被GC回收。在mCallback是通過(guò)handler做的異步回調(diào)培漏,在回調(diào)時(shí)溪厘,finish當(dāng)前activity,但是mSelf還在指向其他引用牌柄。
其實(shí)光從app的功能實(shí)現(xiàn)上畸悬,并不會(huì)產(chǎn)生感官上的差異,但是上面也說(shuō)了珊佣,內(nèi)存泄漏堆積后蹋宦,會(huì)影響你的app性能,嚴(yán)重造成oom咒锻。所以在實(shí)際開發(fā)中冷冗,一定要防止此錯(cuò)誤的產(chǎn)生。
二惑艇、解決方案
簡(jiǎn)單來(lái)說(shuō)贾惦,用戶在退出當(dāng)前界面,即銷毀當(dāng)前activity時(shí)敦捧,如果此時(shí)handler對(duì)象有message在排隊(duì)须板,無(wú)法釋放,就會(huì)導(dǎo)致activity無(wú)法正常銷毀兢卵,從而造成內(nèi)存泄漏习瑰。
解決方案很簡(jiǎn)單:在onDestroy()生命周期中,將handler所有的消息全都移除秽荤,可以有效解決由handler引起的內(nèi)存泄漏甜奄。
- 可以查看谷歌的官方api
public final void removeCallbacksAndMessages([Object] token)
Added in [API level 1]
Remove any pending posts of callbacks and sent messages whose obj is token. Iftoken
is null, all callbacks and messages will be removed.
意思是當(dāng)傳入的參數(shù)為null時(shí),則會(huì)移除所有的callbacks和message窃款,這樣就有效避免了Handler引起的內(nèi)存泄漏课兄。
具體代碼
@Override
protected void onDestroy() {
if(mHandler != null){
mHandler.removeCallbacksAndMessages(null);
}
//do something
super.onDestroy();
}
三、AsynTask引起的內(nèi)存泄漏
其實(shí)AsynTask引起的原因與handler類似晨继,在activity結(jié)束的時(shí)候就結(jié)束了任務(wù)烟阐。但是相對(duì)于其他情況(比如說(shuō)操作網(wǎng)絡(luò)的時(shí)候),doInBackground方法里面還是會(huì)繼續(xù)執(zhí)行紊扬,并且執(zhí)行完之后還會(huì)繼續(xù)onPostExecute方法蜒茄,此時(shí)如果用戶網(wǎng)絡(luò)較慢,還在進(jìn)行網(wǎng)絡(luò)請(qǐng)求中餐屎,用戶沒(méi)耐心了檀葛,不想等,退出當(dāng)前activity腹缩,那么必定會(huì)因?yàn)锳synTask引起的內(nèi)存泄漏屿聋,導(dǎo)致activity無(wú)法正常銷毀空扎。
- 解決方案
@Override
protected void onDestroy() {
if(mMyTask != null && mMyTask.isCancelled()){
//及時(shí)結(jié)束異步任務(wù)
mMyTask.cancel(true);
mMyTask = null;
}
//do something
super.onDestroy();
}
總結(jié)
雖然內(nèi)存泄漏可能是無(wú)感知的,但是長(zhǎng)期如此危害是相當(dāng)?shù)娜蠹ァ=鉀Q內(nèi)存泄漏要從細(xì)節(jié)做起勺卢,一定要受到開發(fā)者的足夠重視。
解決內(nèi)存泄漏有許多入手象对,這里舉的兩個(gè)例子是非常使用,解決方案也非常簡(jiǎn)單宴抚。但是非常讓人忽略勒魔,如果沒(méi)有工具,可能還無(wú)法知道這種現(xiàn)象產(chǎn)生菇曲,所以未了解的童鞋冠绢,可以正好漲漲姿勢(shì)……