WeakReference 弱引用
定義:弱引用嵌灰,與強(qiáng)引用(我們常見(jiàn)的引用方式)相對(duì);特點(diǎn)是:GC在回收時(shí)會(huì)忽略掉弱引用對(duì)象(忽略掉這種引用關(guān)系)背率,即:就算弱引用指向了某個(gè)對(duì)象,但只要該對(duì)象沒(méi)有被強(qiáng)引用指向,該對(duì)象也會(huì)被GC檢查時(shí)回收掉弧岳。
強(qiáng)引用實(shí)例自然不會(huì)被GC回收!
如何引出弱引用业踏?弱引用的實(shí)際用途是什么禽炬?
什么是內(nèi)存泄漏?Java使用有向圖機(jī)制勤家,通過(guò)GC自動(dòng)檢查內(nèi)存中的對(duì)象腹尖;如果GC發(fā)現(xiàn)一個(gè)或一組對(duì)象為不可達(dá)的狀態(tài),則將該對(duì)象從內(nèi)存中回收伐脖。也就是說(shuō):一個(gè)對(duì)象不被任何引用所指向热幔,則該對(duì)象會(huì)在被GC發(fā)現(xiàn)的時(shí)候回收。
可能導(dǎo)致內(nèi)存泄漏的實(shí)例:
Handler mHandler = newHandler() {
????@Override
????publicvoidhandleMessage(Message msg) {
????????mImageView.setImageBitmap(mBitmap);
????};
};
當(dāng)使用內(nèi)部類(或者匿名類)來(lái)創(chuàng)建Handler的時(shí)候讼庇,Handler對(duì)象會(huì)隱式地持有一個(gè)外部類的對(duì)象(通常是Activity)的引用(否則怎么可能通過(guò)Handler來(lái)操作Activity的View绎巨?)。而Handler通常會(huì)伴隨著一個(gè)耗時(shí)的后臺(tái)線程(比如:拉取網(wǎng)絡(luò)圖片)蠕啄;該后臺(tái)線程在任務(wù)執(zhí)行完畢后场勤,通過(guò)消息機(jī)制通知Handler戈锻,然后Handler把圖片更新到界面上。假設(shè)用戶在網(wǎng)絡(luò)請(qǐng)求過(guò)程中關(guān)閉了Activity和媳,正常情況下這個(gè)Activity不再被使用格遭,就有可能被GC回收;但此時(shí)線程尚未執(zhí)行完畢留瞳,而該線程持有Handler的引用(不然怎么發(fā)送消息給Handler拒迅?),Handler又持有Activity的引用她倘,就導(dǎo)致該Activity無(wú)法被回收(內(nèi)存泄漏)坪它,直到網(wǎng)絡(luò)請(qǐng)求結(jié)束(如:圖片下載完畢)。另外如果執(zhí)行了Handler的postDelayed()帝牡,該方法會(huì)將Handler裝入一個(gè)Message往毡,并把該Message推到MessageQueue中,由此產(chǎn)生了一條鏈?zhǔn)浇Y(jié)構(gòu):MessageQueue->Message->Handler->Activity靶溜,導(dǎo)致Activity被持有引用而無(wú)法被回收开瞭。(總結(jié):實(shí)例對(duì)象被其他對(duì)象持有引用,而無(wú)法被回收)
內(nèi)存泄漏的危害是什么罩息??jī)?nèi)存泄漏會(huì)引發(fā)虛擬機(jī)占用內(nèi)存過(guò)高嗤详。對(duì)于Android應(yīng)用程序來(lái)說(shuō),用戶打開(kāi)一個(gè)Activity瓷炮,使用完之后關(guān)閉葱色,內(nèi)存泄漏;執(zhí)行上述步驟多次娘香,程序占用內(nèi)存超過(guò)系統(tǒng)限制苍狰。
如何避免內(nèi)存泄漏?可以使用什么方法烘绽?由此引出了弱引用淋昭。
用于非必需對(duì)象,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次GC發(fā)生之前安接。當(dāng)GC工作時(shí)翔忽,無(wú)論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉只被弱引用關(guān)聯(lián)的對(duì)象
/**
?* <功能描述> 用于加載Bitmap實(shí)例
?*
?* @author Administrator
?*/
publicclassAsyncDrawable extendsBitmapDrawable {
????privatefinalWeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
????publicAsyncDrawable(Resources res, Bitmap bitmap,
????????????BitmapWorkerTask bitmapWorkerTask) {
????????super(res, bitmap);
????????// bitmapWorkerTaskReference實(shí)例關(guān)聯(lián)BitmapWorkerTask
????????bitmapWorkerTaskReference = newWeakReference<BitmapWorkerTask>(
????????????????bitmapWorkerTask);
????}
????publicBitmapWorkerTask getBitmapWorkerTask() {
????????returnbitmapWorkerTaskReference.get();
????}
}
此時(shí)
WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference 關(guān)聯(lián)了
bitmapWorkerTask 實(shí)例(可認(rèn)為兩者是“好朋友”關(guān)系)盏檐;在虛擬機(jī)看來(lái) bitmapWorkerTask 實(shí)例是垃圾時(shí)歇式,但
WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference
不是垃圾。但垃圾并不會(huì)立即被回收胡野,也就是仍然可以使用對(duì)象 bitmapWorkerTask
實(shí)例材失;若該對(duì)象已被清理,則必須重新構(gòu)建對(duì)象给涕,并再一次關(guān)聯(lián)豺憔。
好處在于:可以申請(qǐng)任意多個(gè) bitmapWorkerTask 實(shí)例對(duì)象,并與弱引用對(duì)象關(guān)聯(lián)够庙;使用前恭应,先判斷是否已被釋放;如果已被釋放耘眨,則重新申請(qǐng)昼榛;若未被釋放,則直接使用剔难。WeakReference負(fù)責(zé)了釋放規(guī)則胆屿。
使用了上述代碼后,用戶在關(guān)閉Activity之后偶宫,就算后臺(tái)線程還沒(méi)有結(jié)束非迹,但由于僅有一個(gè)來(lái)自Handler的弱引用指向Activity,所有GC仍然會(huì)在檢查的時(shí)候把Activity回收掉纯趋。