Handler/Runnable錯誤使用方法造成內存泄漏

1.內存泄漏根本原因

內存泄漏的根本原因是:長生命周期的對象持有短生命周期的對象,短生命周期的對象就無法及時釋放。

2.Handler錯誤使用

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Toast.makeText(MainActivity.this, "測試", Toast.LENGTH_SHORT).show();
        }
    };

Handler允許我們發(fā)送延時消息,如果在延時消息未處理完,而此時Handler所在的Activity被關閉,但因為上述Handler用法則可能會導致內存泄漏。首先,Handler是以內部類的形式被創(chuàng)建,那么它將隱性持有外部類的對象,而且,在Toast中還可以MainActivity.this方式顯性持有了MainActivity的對象,那么,在延時消息未處理完時,Handler無法釋放外部類MainActivity的對象,從而導致內存泄漏產生。

3.Handler正確用法

package com.yds.jianshu.mobile;

import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "[MainActivity]";
    private MyHandler handler;
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();

    }
    private void initData(){
        tv = findViewById(R.id.text);
        handler = new MyHandler(this);
        
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (handler!=null){
            handler.removeCallbacksAndMessages(null);
        }
    }


    private static class MyHandler extends Handler{
        private WeakReference<MainActivity>reference;
        public MyHandler(MainActivity activity){
            reference = new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity activity = reference.get();
            if (activity!=null){
                Toast.makeText(activity, "測試", Toast.LENGTH_SHORT).show();
                activity.tv.setText("測試");
            }
           
        }
    }
}

上面代碼中,通過弱引用來協(xié)助Handler的調用

 reference = new WeakReference<>(activity);

4. Runnable錯誤用法

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {

        }
    };

一樣的道理,該使用方法是創(chuàng)建了一個內部類,內部類隱性持有外部類對象的引用,如果Activity結束,Runnable里面的任務沒有處理完,則不會釋放Activity的引用,則Activity無法被回收,造成內存泄漏。

5.Runnable正確用法

    private static class MyRunnable implements Runnable{
        WeakReference<MainActivity> reference;
        public MyRunnable(MainActivity activity){
            reference = new WeakReference<>(activity);
        }
        @Override
        public void run() {
            MainActivity activity = reference.get();
        }
    }

總結

  • 如果直接new一個Handler,則Handler是一個非靜態(tài)內部類,它隱性地持有外部類的對象。如果外部類需要結束,但消息隊列中還有消息未處理完,則Handler不會釋放外部類的對象,從而造成內存泄漏。
  • 如果直接new一個Runnable,Runnable也是一個非靜態(tài)內部類,它隱性地持有外部類的對象,如果外部類需要結束,但Runnable還有任務未處理完,則Runnable不會釋放外部類的對象,從而造成內存泄漏。
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 內存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應用出現內存泄漏的問題。內存泄漏大家都不陌生了,簡單粗俗的講,...
    DreamFish閱讀 869評論 0 5
  • Android 內存泄漏總結 內存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應用出現內存泄漏的問題。內存泄漏...
    _痞子閱讀 1,700評論 0 8
  • 前言 之前研究過一段時間關于 Android 內存泄漏的知識,大致了解了導致內存泄漏的一些原因,但是沒有深入去探究...
    Zackratos閱讀 19,614評論 19 49
  • 【Android 內存泄漏】 引用: ★★★ 【知識必備】內存泄漏全解析,從此拒絕ANR,讓OOM遠離你的身邊,跟...
    Rtia閱讀 987評論 0 2
  • 1 內存泄漏根本原因 內存泄漏的根本原因是:長生命周期的對象持有短生命周期的對象,短生命周期的對象就無法及時釋放。...
    秀葉寒冬閱讀 3,204評論 6 7

友情鏈接更多精彩內容