2016-01-18 17 views
1

我有代碼的活動如下爲什麼處理程序泄漏問題不會發生線程以外主線程

Handler handler = new Handler(){ 
     @Override 
     public void dispatchMessage(Message msg) { 
      super.dispatchMessage(msg); 
     } 
    }; 

的Android工作室皮棉:

處理器參考泄漏

由於此Handler被聲明爲內部類,因此可能會阻止外部類被垃圾收集。 如果處理程序對主線程以外的線程使用Looper或MessageQueue,則不存在問題。如果處理程序使用主線程的Looper或MessageQueue,則需要修復Handler聲明,如下所示:將Handler聲明爲靜態類;在外部類中,實例化WeakReference到外部類並在實例化Handler時將此對象傳遞給Handler;使用WeakReference對象創建對外部類成員的所有引用。

我知道Handler引用泄漏,因爲它擁有強大的活動引用,並且活動不能被垃圾回收收集,但爲什麼Handler泄漏問題不會發生在主線程以外的線程中?主線程生命週期只要應用程序很重要?

回答

0

Android Studio lint說關於Handler 裏面的 Looper或MessageQueue。 一個從Android docs例如:

class LooperThread extends Thread { 
    public Handler mHandler; 

    public void run() { 
     Looper.prepare(); 

     mHandler = new Handler() { 
      public void handleMessage(Message msg) { 
       // process incoming messages here 
      } 
     }; 

     Looper.loop(); 
    } 
} 

這顯然不持有任何活動的引用,因此不泄漏。

1

如果你看看Handler實現,那麼你會發現最初它不會將自己的引用傳遞給任何外部(即Looper)對象。一旦您在post消息中發現了外部參考,this參考將被分配給消息target字段。現在,如果您的消息長期存在(發佈延期較長),那麼它可能會超過您的活動時間,從而導致資源泄漏。實際的原因是主線程消息隊列持有一個消息引用您的處理程序,它也包含對您的活動的引用。當您的處理程序在活動中處於內部靜態時,會發生此引用泄漏。

現在讓我們用主線程消息隊列替換其他線程消息隊列。因爲這是此警告消息正在討論的內容。假設你的處理程序對你的活動仍然是內在的靜態的,但是它使用了其他線程的循環,可以說你想要延遲發佈消息到這個線程。一旦你的延遲消息進入到這個工作線程的消息隊列中,它仍然會引起一個引用泄漏 - 它將會無限期地保留對你的處理程序的引用,它也會引用你的活動。

所以我的理解是,在上述情況下,這個警告並不完全正確。或者也許我錯過了一些東西。

您可能會爭辯說,一旦Activity.onDestroy被調用,此線程可能會終止,這當然會防止引用泄漏。