1. 程式人生 > >Android實現弱引用AsyncTask,將記憶體洩漏置之度外。

Android實現弱引用AsyncTask,將記憶體洩漏置之度外。

AsyncTask可謂是在Android中隱藏很深,曾經叱吒風雲的功夫級人物。它的存在讓網路和UI的通訊變得異常簡單和輕鬆。AsyncTask使用上的簡單也得以讓很多開發者青睞。一般情況下,AsyncTask會作為內部類在Activity或者Fragment中實現,例如:


相信很多朋友都是這麼玩的。但是這樣寫會不會有問題呢?答案是肯定的。

首先,我們知道Java語言是一種強型別,強引用的語言。在一個類中建立內部類時,內部類會預設對外部類持有引用。可以簡單的理解為,外部類作為了一個寄託者將內部類繫結在了自己身上。我們知道Activity或者Fragment是有生命週期存在的。並且AsyncTask多用於處理耗時操作(資料庫,IO讀寫,網路請求等等。。)此時,就會出現一個嚴重的問題:在Activity或者Fragment生命週期結束後,由於AsyncTask的耗時任務尚未完成,導致Activity或者Fragment無法釋放資源。即發生我們經常所聽到的 “記憶體洩漏”。

有朋友可能不明白了,為什麼會產生記憶體洩漏呢?

我們上面提到,由於內部類和外部類的繫結關係,並且AsyncTask的耗時操作導致外部類資源不能被及時GC。Java中預設的引用持有都是強引用型別。例如我們直接new出來的物件。為了避免這些問題,Java還為我們提供了軟引用,弱引用,無引用持有等等一些工具。弱引用和軟引用的作用幾乎相同。都是在資源緊缺的情況下被得以回收。

所以,解決這個問題的關鍵之處就在於不要對外部類持有強引用,或者將內部類定義成static型別,讓其與外部類擁有相同的生命週期。此時有朋友可能一臉懵逼,為啥定義成static就可以了。哈哈,你想哇,static靜態的內部類屬於外部類的靜態成員,當外部類初始化時它才會被初始化,同樣,當外部類被釋放時,它也會被同時釋放。也就是內部類與外部類同生共死。但是使用static型別的同樣需要我們將在asyncTask中使用的變數也宣告為static,數量少的情況下還是可以接受的,但是很多的static情況下,容易讓記憶體吃緊,GC頻繁。所以,合適的解決方案就是使用弱引用來改變內部類對外部類的引用關係。

即我們可以自定義一個Weak形式的AsyncTask,讓其持有外部類的弱引用:


可以看到上面我們定義了一個WeakAsyncTask類繼承自AsyncTask。在類中我們使用WeakRefrences來弱引用外部Context。所以,當外部類需要釋放時,會立刻被GC所回收。避免了記憶體洩漏的問題。

使用方式很簡單:

ok,本篇部落格講解了AsyncTask作為內部類導致記憶體洩漏以及以及如何解決該問題,相信大家也有了深刻認識。有問題的可以給我留言咯~