1. 程式人生 > >Android記憶體溢位與優化(四)——防止Handler導致的記憶體洩露

Android記憶體溢位與優化(四)——防止Handler導致的記憶體洩露

在Android中,子執行緒不能直接更新主執行緒的UI,因此提供了Handler來方便我們操作。在子執行緒呼叫handler可以直接傳送Message加入MessageQueue,Looper取出Message執行操作,這樣就完成了從子執行緒到主執行緒的UI更新。但是,如果Looper取出的Message執行的操作是使用handler再發訊息(傳送的訊息和之前一樣),這樣就形成了死迴圈,這樣handler一直被持有引用,無法釋放記憶體,導致記憶體洩露。

*****個人經驗狹隘,難免有所疏漏,若有問題,懇請斧正!*****

1.什麼時候會需要迴圈handler發訊息?

前面說handler形成死迴圈,會導致記憶體洩露。可是大家會想“誰會這麼傻,沒事弄個死迴圈?

”。記得App裡面常見的廣告欄嗎?會一直迴圈展示圖片,這個時候就可能需要用到handler傳送迴圈的延時訊息。這裡假設使用ViewPager迴圈展示圖片,大致程式碼如下:

public class Demo extends AppCompatActivity {


    private static final int NEXT_PAGE = 1;

    private ViewPager mViewPager;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == NEXT_PAGE) {
                nextPage();//收到訊息後,呼叫切換下一頁的程式碼
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        //其他操作……

        nextPage();
    }

    private void nextPage() {
        //切換至下一頁
        int currentItem = mViewPager.getCurrentItem();
        mViewPager.setCurrentItem(++currentItem);
        mHandler.sendEmptyMessageDelayed(NEXT_PAGE, 4000);//4秒後切換下一頁
    }
}

可以看到,由於mHandler每次傳送的延時4的秒訊息,接收到訊息後又繼續呼叫了傳送延時訊息的方法nextPage(),這樣就陷入了死迴圈。mHandler一直被呼叫,使Activity一直被持有引用,即便是Activity銷燬了,也不會被釋放掉記憶體,導致記憶體洩露。

2.如何解決handler迴圈導致的記憶體洩露?

(一)使用WeakReference,使垃圾回收器傾向於回收該物件

        Java中物件有強、軟、弱、虛四種引用,垃圾回收器優先回收順序是虛>弱>軟,不會回收持有強引用的物件(一直被持有強引用是導致記憶體洩露的原因)。平時建立的物件(例如Person person = new Person();),都是強引用,但是一旦使用完後,就不再持有引用,強引用消失,垃圾回收器就會來回收這片記憶體。而handler的迴圈使其引用一直不消失,所以不會被垃圾回收器回收,導致記憶體洩露。解決的程式碼如下:

private MyHandler mHandler = new MyHandler(DemoActivity.this);

    private static class MyHandler extends Handler {

        private final WeakReference<DemoActivity> mActivity;

        MyHandler(DemoActivity activity) {
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            DemoActivity activity = mActivity.get();
            if (activity != null) {

            }
        }
    }

         使用WeakReference後,該物件的引用變成了弱引用,垃圾回收器會優先回收沒有引用的物件,當記憶體不足時就會回收這種不穩定的弱引用物件,釋放出記憶體。

            (二)在Acticity銷燬時,移除所有訊息

         既然handler的所有Message、Callback都被移除了,自然就消除了迴圈導致的持續引用問題。解決的程式碼如下:

@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);//移除MessageQueue內所有的Message、Callback
    }

        (三)在Application類中,定義一個全域性的handler

         Application是一個全域性的類,在App啟動時啟動,只有App關閉時才會銷燬,所以完全不會存在記憶體洩露問題。設定程式碼如下:

/**
 * 自定義Application,進行全域性初始化
 *
 * @author ALion on 2016/10/13 20:46
 */
public class MyApplication extends Application {

    private static Handler mHandler;


    @Override
    public void onCreate() {
        super.onCreate();

        mHandler = new Handler();
    }
    
    public static Handler getHandler() {
        return mHandler;
    }
    
}

——加油!


相關推薦

Android記憶體溢位優化——防止Handler導致記憶體洩露

在Android中,子執行緒不能直接更新主執行緒的UI,因此提供了Handler來方便我們操作。在子執行緒呼叫handler可以直接傳送Message加入MessageQueue,Looper取出

Android開發--圖形影象動畫--AnimationListener簡介

                     就像Button控制元件有監聽器一樣,動畫效果也有監聽器,只需要實現AnimationListener就可以實現對動畫效果的監聽,其中需要過載三個函式,就是下面的這幾個函式:private class MyListenr implements AnimationLis

Unity優化大全之CPU-GC(記憶體回收)和Sricpt

前言:        對於GC,大家可能不陌生把,也就是記憶體回收。同時筆者在做自己的小遊戲中發現很多細節都會影響GC,現在就給大家梳理下一些需要注意的地方。 進入主題:        在說C

深入理解Android音視訊同步機制MediaSync的使用原理

MedaiSync是android M新加入的API,可以幫助應用視音訊的同步播放,如同官網介紹的 From Andriod M: MediaSync: class which helps applications to synchronously r

Android 記憶體溢位解決方案 整理

<span style="font-size:14px;">在最近做的工程中發現載入的圖片太多或圖片過大時經常出現OOM問題,找網上資料也提供了很多方法,但自己感覺有點亂,特此,今天在不同型號的三款安卓手機上做了測試,因為有效果也有結果,今天小馬就做個詳細的總結

Android 記憶體溢位解決方案OOM 整理總結

在最近做的工程中發現載入的圖片太多或圖片過大時經常出現OOM問題,找網上資料也提供了很多方法,但自己感覺有點亂,特此,今天在不同型號的三款安卓手機上做了測試,因為有效果也有結果,今天小馬就做個詳細的總結,以供朋友們共同交流學習,也供自己以後在解決OOM問題上有所提高,提前講下,片幅有點長,涉及的東西太

Android記憶體溢位解決方案OOM

眾所周知,每個Android應用程式在執行時都有一定的記憶體限制,限制大小一般為16MB或24MB(視平臺而定)。因此在開發應用時需要特別關注自身的記憶體使用量,而一般最耗記憶體量的資源,一般是圖片、音訊檔案、視訊檔案等多媒體資源;由於Android系統對音訊、視訊等資源做了邊解析便播放的處理,使用時並不

Android系統性能優化44---全面&詳細的記憶體優化指南

前言在 Android開發中,效能優化策略十分重要本文主要講解效能優化中的記憶體優化,希望你們會喜歡目錄1. 定義優化處理 應用程式的記憶體使用、空間佔用2. 作用避免因不正確使用記憶體 & 缺乏管理,從而出現 記憶體洩露(ML)、記憶體溢位(OOM)、記憶體空間佔用

深度學習框架TensorFlow學習應用——擬合問題、優化

一、擬合 1)迴歸問題: 過擬合儘量去通過每一個樣本點,誤差為零。假如有一個新的樣本點: 會發現過擬合的偏差會很大。 2)分類問題: 同樣的當得到新的樣本點後,過擬合的錯誤率可能會提高。 3)防止過擬合: 1.增加資料集 2.正則化方

讀懂作業系統之虛擬記憶體TLB快取cache關係篇

前言 前面我們講到通過TLB快取頁表加快地址翻譯,通過上一節快取原理的講解為本節做鋪墊引入TLB和快取的關係,同時我們來完整梳理下從CPU產生虛擬地址最終對映為實體地址獲取資料的整個過程是怎樣的,若有錯誤之處,還請批評指正。 TLB和快取序列訪問(Serial TLB & Cache Access)

模型類的設計實現

介紹 傳遞數據 規則 添加 play using ota 實體類 重要 實體類是現實實體在計算機中的表示。它貫穿於整個架構,負擔著在各層次及模塊間傳遞數據的職責。 一般來說,實體類可以分為“貧血實體類”和“充血實體類”,前者僅僅保存實體的屬性,而後者還包含一些實體間的關系與

三維渲染引擎設計實踐

方式 lora 扇面 多個 幀緩存 binding osg smo tco 五、繪制幾何對象和文字 幀緩存(Frame Buffer)為用戶與顯示設備交互的一個接口,將顯示的畫面抽象成一塊可以進行讀寫操作的內存區域。 幀緩存的每一個存儲單元都對應顯示屏上的一個像素。整個緩存

Spring Boot 揭秘實戰 配置文件篇 - 有哪些很棒的特性

real randint 開發人員 hat mod 配置管理 bsp footer tar 文章目錄 1. 使用屬性文件2. YAML文件 1.1. 自定義屬性 1.2. 參數引用 1.3. 隨機數屬性 1.4. application-{profile}.proper

讀書筆記--C陷阱缺陷

缺陷 目標 命名 整合 編譯器 修飾 調用 檢查 含義 第四章 1. 連接器 C語言的一個重要思想就是分別編譯:若幹個源程序可在不同的時候單獨進行編譯,恰當的時候整合到一起。 連接器一般與C編譯器分離,其輸入是一組目標模塊(編譯後的模塊)和庫文

Docker學習實踐

registry docker 四、倉庫管理 1.創建本地倉庫 ①獲取官方registry鏡像 [root@dockertest ~]# docker run -d -p 5000:5000 --restart=always --name registry registry:2 Unable to f

0x10軟考|網路工程師經驗分享之網路互聯網際網路

目錄 一、傳輸層協議TCP 二、傳輸層協議UDP 三、常見應用層協議 一、傳輸層協議TCP TCP協議:傳輸控制協議,面向位元組流按順序、連線、可靠、全雙工,可變滑動視窗、緩衝累積傳送。協議號6 下面是TCP段(斷頭),TCP頭(傳輸頭),TCP包

Android框架原始碼解析之Picasso

這次要分析的原始碼是 Picasso 2.5.2 ,四年前的版本,用eclipse寫的,但不影響這次我們對其原始碼的分析 地址:https://github.com/square/picasso/tree/picasso-parent-2.5.2 Picasso的簡單使用

認證鑑權API許可權控制在微服務架構中的設計實現

引言: 本文系《認證鑑權與API許可權控制在微服務架構中的設計與實現》系列的完結篇,前面三篇已經將認證鑑權與API許可權控制的流程和主要細節講解完。本文比較長,對這個系列進行收尾,主要內容包括對授權和鑑權流程之外的endpoint以及Spring Security過濾器部分踩坑的經歷。歡迎閱讀本系列

Git的學習使用——Git 工作區、暫存區和版本庫

基本概念 我們先來理解下Git 工作區、暫存區和版本庫概念 工作區:就是你在電腦裡能看到的目錄。 暫存區:英文叫stage, 或index。一般存放在 ".git目錄下" 下的index檔案(.git/index)中,所以我們把暫存區有時也叫作索引(index)。 版本庫:工作區有一個隱

mysql資料庫優化-專案實戰

在flask專案中,防止隨著時間的流逝,資料庫資料越來越多,導致介面訪問資料庫速度變慢。所以自己填充資料進行測試及 mysql優化 1.插入資料: 通過指令碼,使用多程序,每100次提交資料 import multiprocessing import time from fla