Android中使用Handler造成的內(nèi)存泄露如何解決-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)Android中使用Handler造成的內(nèi)存泄露如何解決,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

石林網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),石林網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為石林千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的石林做網(wǎng)站的公司定做!

一、什么是內(nèi)存泄露?

  Java使用有向圖機(jī)制,通過(guò)GC自動(dòng)檢查內(nèi)存中的對(duì)象(什么時(shí)候檢查由虛擬機(jī)決定),如果GC發(fā)現(xiàn)一個(gè)或一組對(duì)象為不可到達(dá)狀態(tài),則將該對(duì)象從內(nèi)存中回收。也就是說(shuō),一個(gè)對(duì)象不被任何引用所指向,則該對(duì)象會(huì)在被GC發(fā)現(xiàn)的時(shí)候被回收;另外,如果一組對(duì)象中只包含互相的引用,而沒(méi)有來(lái)自它們外部的引用(例如有兩個(gè)對(duì)象A和B互相持有引用,但沒(méi)有任何外部對(duì)象持有指向A或B的引用),這仍然屬于不可到達(dá),同樣會(huì)被GC回收。

  Android中使用Handler造成內(nèi)存泄露的原因

private Handler handler = new Handler()
 {
   public void handleMessage(android.os.Message msg)
     {
      if (msg.what == 1) 
        {
        noteBookAdapter.notifyDataSetChanged();
       }
    }
 };

  上面是一段簡(jiǎn)單的Handler的使用。當(dāng)使用內(nèi)部類(lèi)(包括匿名類(lèi))來(lái)創(chuàng)建Handler的時(shí)候,Handler對(duì)象會(huì)隱式地持有一個(gè)外部類(lèi)對(duì)象(通常是一個(gè)Activity)的引用(不然你怎么可能通過(guò)Handler來(lái)操作Activity中的View?)。而Handler通常會(huì)伴隨著一個(gè)耗時(shí)的后臺(tái)線程(例如從網(wǎng)絡(luò)拉取圖片)一起出現(xiàn),這個(gè)后臺(tái)線程在任務(wù)執(zhí)行完畢(例如圖片下載完畢)之后,通過(guò)消息機(jī)制通知Handler,然后Handler把圖片更新到界面。然而,如果用戶(hù)在網(wǎng)絡(luò)請(qǐng)求過(guò)程中關(guān)閉了Activity,正常情況下,Activity不再被使用,它就有可能在GC檢查時(shí)被回收掉,但由于這時(shí)線程尚未執(zhí)行完,而該線程持有Handler的引用(不然它怎么發(fā)消息給Handler?),這個(gè)Handler又持有Activity的引用,就導(dǎo)致該Activity無(wú)法被回收(即內(nèi)存泄露),直到網(wǎng)絡(luò)請(qǐng)求結(jié)束(例如圖片下載完畢)。另外,如果你執(zhí)行了Handler的postDelayed()方法,該方法會(huì)將你的Handler裝入一個(gè)Message,并把這條Message推到MessageQueue中,那么在你設(shè)定的delay到達(dá)之前,會(huì)有一條MessageQueue -> Message -> Handler -> Activity的鏈,導(dǎo)致你的Activity被持有引用而無(wú)法被回收。

二、內(nèi)存泄露的危害

  內(nèi)存泄露的危害就是會(huì)使虛擬機(jī)占用內(nèi)存過(guò)高,導(dǎo)致OOM(內(nèi)存溢出),程序出錯(cuò)。

  對(duì)于Android應(yīng)用來(lái)說(shuō),就是你的用戶(hù)打開(kāi)一個(gè)Activity,使用完之后關(guān)閉它,內(nèi)存泄露;又打開(kāi),又關(guān)閉,又泄露;幾次之后,程序占用內(nèi)存超過(guò)系統(tǒng)限制,F(xiàn)C。

三、解決方案

使用Handler導(dǎo)致內(nèi)存泄露的解決方法

方法一:通過(guò)程序邏輯來(lái)進(jìn)行保護(hù)。

1.在關(guān)閉Activity的時(shí)候停掉你的后臺(tái)線程。線程停掉了,就相當(dāng)于切斷了Handler和外部連接的線,Activity自然會(huì)在合適的時(shí)候被回收。

2.如果你的Handler是被delay的Message持有了引用,那么使用相應(yīng)的Handler的removeCallbacks()方法,把消息對(duì)象從消息隊(duì)列移除就行了。

方法二:將Handler聲明為靜態(tài)類(lèi)。

PS:在Java 中,非靜態(tài)的內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)都會(huì)隱式地持有其外部類(lèi)的引用,靜態(tài)的內(nèi)部類(lèi)不會(huì)持有外部類(lèi)的引用。

靜態(tài)類(lèi)不持有外部類(lèi)的對(duì)象,所以你的Activity可以隨意被回收。由于Handler不再持有外部類(lèi)對(duì)象的引用,導(dǎo)致程序不允許你在Handler中操作Activity中的對(duì)象了。所以你需要在Handler中增加一個(gè)對(duì)Activity的弱引用(WeakReference)。

代碼如下:

static class MyHandler extends Handler
  {
    WeakReference<Activity> mWeakReference;
    public MyHandler(Activity activity) 
    {
      mWeakReference=new WeakReference<Activity>(activity);
    }
    @Override
    public void handleMessage(Message msg)
    {
      final Activity activity=mWeakReference.get();
      if(activity!=null)
      {
        if (msg.what == 1)
        {
          noteBookAdapter.notifyDataSetChanged();
        }
      }
    }
  }

PS:什么是WeakReference?

  WeakReference弱引用,與強(qiáng)引用(即我們常說(shuō)的引用)相對(duì),它的特點(diǎn)是,GC在回收時(shí)會(huì)忽略掉弱引用,即就算有弱引用指向某對(duì)象,但只要該對(duì)象沒(méi)有被強(qiáng)引用指向(實(shí)際上多數(shù)時(shí)候還要求沒(méi)有軟引用,但此處軟引用的概念可以忽略),該對(duì)象就會(huì)在被GC檢查到時(shí)回收掉。對(duì)于上面的代碼,用戶(hù)在關(guān)閉Activity之后,就算后臺(tái)線程還沒(méi)結(jié)束,但由于僅有一條來(lái)自Handler的弱引用指向Activity,所以GC仍然會(huì)在檢查的時(shí)候把Activity回收掉。這樣,內(nèi)存泄露的問(wèn)題就不會(huì)出現(xiàn)了。

關(guān)于Android中使用Handler造成的內(nèi)存泄露如何解決就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

名稱(chēng)欄目:Android中使用Handler造成的內(nèi)存泄露如何解決-創(chuàng)新互聯(lián)
轉(zhuǎn)載來(lái)源:http://www.muchs.cn/article16/dssogg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、關(guān)鍵詞優(yōu)化、網(wǎng)站策劃、域名注冊(cè)、標(biāo)簽優(yōu)化品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司