★30.內(nèi)存泄漏

內(nèi)存泄漏的主要原因

  • 生命周期長的對象持有了生命周期短的對象蟋软,導(dǎo)致生命周期短的對象無法釋放內(nèi)存。(即長的不能持有短的泊碑。)

context情形

情景描述

  • 生命周期長的對象保留了生命周期短的context瓤介,如 單例類 保留了Activitycontext

解決方案

  • 在獲取到生命周期短的context時漂辐,不保留此context衡蚂,而通過Context.getApplicationContext()獲取應(yīng)用程序的context窿克。由于保留應(yīng)用程序的context的對象生命周期不如應(yīng)用程序長,所以不會出現(xiàn)問題毛甲。

static存儲內(nèi)部類對象

情景描述

  • mResource的生命周期是跟應(yīng)用程序一樣長的年叮,而且由于TestResource內(nèi)部類 ,會保留 外部類 對象的引用(即Activity)玻募,所以Activity無法釋放只损,內(nèi)存泄漏。
public class MainActivity extends AppCompatActivity {
    private static TestResource mResource = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(mManager == null){
            mManager = new TestResource();
        }
        //...
    }
    class TestResource {
        //...
    }
}

解決方案

內(nèi)部類(Inner Class) 改為 嵌套類(Nested Class) 七咧。

線程相關(guān)

情景描述

  • 都是因為 內(nèi)部類 對象(此處為 匿名內(nèi)部類 )保留了 外部類 對象的引用導(dǎo)致的跃惫。

情景一

// 無法保證此匿名內(nèi)部類所持有的外部類對象的生命長于10秒
new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... params) {
        SystemClock.sleep(10000);
        return null;
    }
}.execute();

情景二

// 無法保證此段代碼的匿名內(nèi)部類所持有的外部類對象的生命長于10秒
new Thread(new Runnable() {
    @Override
    public void run() {
        SystemClock.sleep(10000);
    }
}).start();

解決方案

  • 改用 嵌套類(Nested Class) ,如果需要 外部類 的引用艾栋,則通過 構(gòu)造方法 傳遞進去爆存,然后使用 弱引用 保留。

Handler情形

情景描述

  1. 線程 保留了Looper的引用蝗砾。
  2. Looper保留了MessageQueue的引用先较。
  3. MessageQueue保留了Message的引用携冤。
  4. Message保留了Handler的引用。
  5. 導(dǎo)致Handler的生命周期可能與 線程 一樣長闲勺。
  6. 若此時同時滿足以下兩個條件:
    1. Handler內(nèi)部類(Inner Class噪叙,包括匿名內(nèi)部類) ,即會保留 外部類 對象的引用霉翔。
    2. 外部類 對象的生命周期短于 線程 ,如Activity苞笨。
  7. 就會導(dǎo)致此 外部類 對象在 線程 釋放之前無法釋放债朵,引發(fā) 內(nèi)存泄漏

解決方案

思路一:破壞條件1

  • Handler成為 嵌套類(Nested Class) 瀑凝,若要訪問原來的 外部類 序芦,就只需要使用 弱引用 來保留 外部類 對象的引用。
// 將Handler定義為嵌套類(static內(nèi)部類)以避免內(nèi)存泄漏粤咪。
private static class RequestHandler extends Handler {
    private WeakReference<Activity> mWeakRef;

    // 可以在構(gòu)造函數(shù)中傳入外部類對象谚中,用WeakReference保留此對象的引用,這樣可以避免內(nèi)存泄漏寥枝。
    public RequestHandler(Activity activity) {
        mWeakRef = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        if (msg.what == /* 消息 */) {
            // 先判斷WeakReference指向的對象還存在宪塔。
            if (mWeakRef.get() == null) {
                return;
            }
            // 使用WeakReference.get()來獲取對象,并使用
            Activity activity = mWeakRef.get();
        }
    }
}

思路二:破壞條件2

  • 外部類 的對象的生命周期不短于 線程 囊拜,例如Activity就不能作為Handler外部類 某筐,而 線程 可以。

資源未釋放

  • 對于使用了BraodcastReceiver冠跷,ContentObserver南誊,FileCursor蜜托,Stream抄囚,Bitmap等資源的使用,應(yīng)該在Activity銷毀時及時關(guān)閉或者注銷橄务,否則這些資源將不會被回收幔托,造成 內(nèi)存泄漏

LeakCanary

內(nèi)存泄漏檢測工具仪糖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柑司,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子锅劝,更是在濱河造成了極大的恐慌攒驰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件故爵,死亡現(xiàn)場離奇詭異玻粪,居然都是意外死亡隅津,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門伦仍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人很洋,你說我怎么就攤上這事充蓝。” “怎么了喉磁?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵谓苟,是天一觀的道長。 經(jīng)常有香客問我协怒,道長涝焙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任孕暇,我火速辦了婚禮仑撞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘妖滔。我一直安慰自己隧哮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布座舍。 她就那樣靜靜地躺著近迁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪簸州。 梳的紋絲不亂的頭發(fā)上鉴竭,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音岸浑,去河邊找鬼搏存。 笑死,一個胖子當(dāng)著我的面吹牛矢洲,可吹牛的內(nèi)容都是我干的璧眠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼读虏,長吁一口氣:“原來是場噩夢啊……” “哼责静!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盖桥,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灾螃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后揩徊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腰鬼,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡嵌赠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了熄赡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姜挺。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖彼硫,靈堂內(nèi)的尸體忽然破棺而出炊豪,到底是詐尸還是另有隱情,我是刑警寧澤拧篮,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布溜在,位于F島的核電站,受9級特大地震影響他托,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仆葡,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一赏参、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沿盅,春花似錦把篓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窖铡,卻和暖如春疗锐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背费彼。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工滑臊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人箍铲。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓雇卷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颠猴。 傳聞我的和親對象是個殘疾皇子关划,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題。內(nèi)存泄漏...
    _痞子閱讀 1,636評論 0 8
  • 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題翘瓮。內(nèi)存泄漏大家都不陌生了贮折,簡單粗俗的講,...
    宇宙只有巴掌大閱讀 2,363評論 0 12
  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題资盅。內(nèi)存泄漏...
    apkcore閱讀 1,221評論 2 7
  • 她接到家里的電話脱货,說家里的雪里蕻要抽芯了岛都,要回家趕緊收了。接完電話后振峻,她便歸心似箭臼疫,頗有些心不在焉。 她小心翼翼想...
    三千晚風(fēng)閱讀 1,296評論 12 22