Android Handler引發(fā)的內(nèi)存泄漏

相信很多人都這樣用過Handler:

Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        //更新UI
        //...
        super.handleMessage(msg);
    }
};
new Thread(new Runnable() {
    @Override
    public void run() {
        //耗時(shí)操作
        //...
        handler.sendEmptyMessage(0);
    }
}).start();

很常見的一段段碼颖医,對沒錯检激,但是確實(shí)發(fā)生了內(nèi)存泄漏。假如當(dāng)在處理耗時(shí)操作的時(shí)候允蜈,可能是某段網(wǎng)絡(luò)請求磷箕,也有可能是很復(fù)雜的計(jì)算选酗,這時(shí)用戶等的不耐煩了退出當(dāng)前界面,由于異步操作岳枷,此時(shí)雖然界面銷毀了芒填,但是任務(wù)還在繼續(xù)呜叫,由于線程中,引用這當(dāng)前Activity中的對象handler殿衰,而handler對象又隱式的應(yīng)用了當(dāng)前的Activity朱庆,因此雖然界面銷毀了,但是Activity并不會被回收闷祥。當(dāng)任務(wù)執(zhí)行完后娱颊,調(diào)用了handler方法,方法中又調(diào)用了更新界面蜀踏,就會出現(xiàn)空指針異常崩潰维蒙。這算是最好的情況了,更嚴(yán)重的是由于Activity無法被銷毀果覆,那么就是占著那個地方不做事颅痊,這就是所謂的站著茅坑不拉屎。那么這塊資源便浪費(fèi)了局待,當(dāng)用戶來回反復(fù)切換的時(shí)候斑响,資源占用越來越大,最終就算不空指針異常 也會出現(xiàn)OOM,這是由于內(nèi)存泄漏導(dǎo)致的钳榨。

內(nèi)存泄露的危害
只有一個舰罚,那就是虛擬機(jī)占用內(nèi)存過高,導(dǎo)致OOM(內(nèi)存溢出)薛耻,程序出錯营罢。對于Android應(yīng)用來說,就是你的用戶打開一個Activity饼齿,使用完之后關(guān)閉它饲漾,內(nèi)存泄露;又打開缕溉,又關(guān)閉考传,又泄露;幾次之后证鸥,程序占用內(nèi)存超過系統(tǒng)限制僚楞。

解決方案

  1. 在關(guān)閉Activity的時(shí)候停掉你的后臺線程任務(wù)。線程停掉了枉层,就相當(dāng)于切斷了Handler和外部連接的線泉褐,Activity自然會在合適的時(shí)候被回收。
  2. 如果你的Handler是被delay的Message持有了引用鸟蜡,那么使用相應(yīng)的Handler的removeCallbacks()方法膜赃,把消息對象從消息隊(duì)列移除就行了。
  3. 我們換一種寫法矩欠,將handler對象聲明成靜態(tài)內(nèi)部類财剖,靜態(tài)類不持有外部類的對象,所以你的Activity可以隨意被回收癌淮。
private TestHandler testHandler=new TestHandler();
static class TestHandler extends Handler{
    @Override
    public void handleMessage(Message msg) {
        //更新界面操作
        //...
        super.handleMessage(msg);
    }
}

很快你會發(fā)現(xiàn)編譯無法通過躺坟。因?yàn)樯厦嬲f過了。靜態(tài)類是不持有外部類的對象的乳蓄,因此如果你在里面寫了更新界面的操作當(dāng)然會編譯無法通過咪橙。解決辦法當(dāng)然有,就在靜態(tài)類中在增加一個外部類的弱引用虚倒。

static class MyHandler extends Handler{
    private WeakReference<SearchContantActivity> mContext;
    public MyHandler(SearchContantActivity activity){
        mContext=new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        if(msg.what==0){
            SearchContantActivity activity=mContext.get();
            if(activity!=null){
                activity.xxx
            }
        }
        super.handleMessage(msg);
    }
}

但是這種仍然會出現(xiàn)異常美侦,當(dāng)你的界面退出后,界面的控件都會被銷毀了魂奥,此時(shí)異步任務(wù)執(zhí)行完,觸發(fā)了handler發(fā)送消息菠剩,這時(shí)handler仍然會受到,從弱引用中拿到的Activity還是存在的耻煤,這時(shí)候你在去更新界面具壮,那么理所當(dāng)然就發(fā)生了NullPointException.所以最好的辦法就是界面在正常發(fā)送handler,界面銷毀就不發(fā)送handler哈蝇,徹底切斷它與Activity的聯(lián)系棺妓,那么就一勞永逸了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炮赦,一起剝皮案震驚了整個濱河市怜跑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吠勘,老刑警劉巖性芬,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異看幼,居然都是意外死亡批旺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門诵姜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汽煮,“玉大人,你說我怎么就攤上這事棚唆∠境啵” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵宵凌,是天一觀的道長鞋囊。 經(jīng)常有香客問我,道長瞎惫,這世上最難降的妖魔是什么溜腐? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任译株,我火速辦了婚禮,結(jié)果婚禮上挺益,老公的妹妹穿的比我還像新娘歉糜。我一直安慰自己,他們只是感情好望众,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布匪补。 她就那樣靜靜地躺著,像睡著了一般烂翰。 火紅的嫁衣襯著肌膚如雪夯缺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天甘耿,我揣著相機(jī)與錄音踊兜,去河邊找鬼。 笑死棵里,一個胖子當(dāng)著我的面吹牛润文,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播殿怜,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼典蝌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了头谜?” 一聲冷哼從身側(cè)響起骏掀,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柱告,沒想到半個月后截驮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡际度,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年葵袭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乖菱。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡坡锡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窒所,到底是詐尸還是另有隱情鹉勒,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布吵取,位于F島的核電站禽额,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皮官。R本人自食惡果不足惜脯倒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一实辑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藻丢,春花似錦徙菠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缺狠。三九已至问慎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挤茄,已是汗流浹背如叼。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留穷劈,地道東北人笼恰。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像歇终,于是被迫代替她去往敵國和親社证。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,513評論 25 707
  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題评凝。內(nèi)存泄漏...
    _痞子閱讀 1,625評論 0 8
  • 這幾天發(fā)生了很多事情追葡,這些事情對我來說有強(qiáng)大的沖擊力,而來得有點(diǎn)突然奕短,我有點(diǎn)蒙圈宜肉,但也想去看看這些事情發(fā)生...
    如水的日記閱讀 240評論 0 0
  • 如果沒有明天谬返,我今天一定要和路過的每一個人,每一個小動物日杈,每一株植物微笑遣铝; 如果沒有明天,我一定要好好感謝那些出現(xiàn)...
    心庭閱讀 404評論 0 1
  • 我是誰达椰? 我是一位程序員翰蠢,準(zhǔn)確的說是前端工程師,略帶調(diào)侃的稱作“碼農(nóng)”啰劲,專攻web梁沧,生活在上海這座擁擠的城市。在網(wǎng)...
    錯碼匠閱讀 267評論 0 0