1. 程式人生 > >Android Handler 避免記憶體洩漏之清空佇列

Android Handler 避免記憶體洩漏之清空佇列

Android開發經常會用到handler,但是我們發現每次使用Handler都會出現:This Handler class should be static or leaks might occur(null)這樣的提示。Android lint就是為了提示我們,這樣使用Handler會容易造成記憶體洩漏。但是你會發現其實改成static並沒有什麼用。因為這並沒有解決這個問題的根本。

  首先,我們得確認,為什麼會有記憶體洩漏?因為Handler是基於訊息的。每次new 出Handler,都會建立一個訊息佇列用於處理你使用handler傳送的訊息,形如:handler.send***Message。由於訊息的傳送總是會有先來後到的區別(如果只是這樣都還好,畢竟再慢也不會太久,總歸可以跑完,可能會延遲個幾秒),但是如果你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等傳送延遲訊息的時候,那基本記憶體洩漏發生的概率已經在90%以上了。

     我舉個通常的例子,就是我們在Activity中使用handler來更新UI控制元件,這是比較常見的。

複製程式碼
 1 public class DemoActivity extends Activity {
 2 
 3     private Handler mHandler; 
 4 
 5     protected void onCreate(Bundle savedInstanceState) {
 6         mHandler = new Handler();
 7 
 8      mHandler.postDelayed(new Runnable() {
 9        Log.i("wytings","-----------postDelayed-------");
10 view.setVisibility(View.GONE); 11 }, 50000); 12 ... 13 } 14   
複製程式碼

      如果我們瘋狂的對這個Activity進行橫屏和豎屏切換的話,那麼Activity就會不斷的被銷燬和重建。理論上被關閉的Activity應該會再特定時候被回收,也就是我們的記憶體會在一定的範圍內上下起伏,但是實際上,會發現消耗的記憶體會隨著切換橫屏的次數一直慢慢增加。這其實已經說明我們的記憶體洩漏了,如果你會檢視記憶體,你會發現裡面有成堆的DemoActivity例項沒辦法回收。

  這是因為view中使用的Context就是當前的Activity,而這個runnable一旦被post,就會一直存在於佇列裡面,直到時間到了,被執行。意思是這個時間段內Activity即使已經被destroy了但是這個物件還是沒辦法回收,你會發現50秒好,會有一堆"-----------postDelayed-------"的log打印出來,雖然你已經被這個應用關閉了並且你以為即使列印也應該只打印一次……

  那怎麼樣才可以避免這中問題呢,如果你網上一搜你會看到很多關於弱引用的文章。這確實是一個解決的辦法。其原理就是讓所有在handler裡面使用的物件都變成弱引用,目的就是為了可以在Android回收記憶體的時候,可以直接回收掉。我真覺得如果只是寫這種辦法的人,絕對是屬於拷貝黨,因為這完全是就事論事。你想想就明白,我們寫這個Handler是因為我們要使用它。怎麼可以通過這種弱引用的辦法去處理這類問題呢?讓JVM想回收就回收?!如果這樣,那我們還需要在使用Bitmap的時候,recycle()幹嘛,還不如直接弄成軟引用得了。

這裡需要再插播一下關於Java裡面引用的知識:

強引用(Strong Reference) 預設引用。如果一個物件具有強引用,垃圾回收器絕不會回收它。在記憶體空 間不足時,Java虛擬機器寧願丟擲OutOfMemory的錯誤,使程式異常終止,也不會強引用的物件來解決記憶體不足問題。
軟引用(SoftReference) 如果記憶體空間足夠,垃圾回收器就不會回收它,如果記憶體空間不足了,就會回收這些物件的記憶體。
弱引用(WeakReference) 在垃圾回收器一旦發現了只具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體。
虛引用(PhantomReference) 如果一個物件僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收。

      如果你運氣好,你會碰到一些除了寫弱引用這個方法後,還有一個就是handler.removeCallbacksAndMessages(null);,就是移除所有的訊息和回撥,簡單一句話就是清空了訊息佇列。注意,不要以為你post的是個Runnable或者只是sendEmptyMessage。你可以看一下原始碼,在handler裡面都是會把這些轉成正統的Message,放入訊息佇列裡面,所以清空佇列就意味著這個Handler直接被打成原型了,當然也就可以回收了。

  所以,我覺得最好的辦法就是你在使用Handler的時候,在外面的Activity或者Fragment中的關閉方法中,如onDestroy中呼叫一下handler.removeCallbacksAndMessages(null);就可以了,不應該改成軟引用。

轉自:http://www.cnblogs.com/wytings/p/5225278.html

相關推薦

Android Handler 避免記憶體洩漏佇列

Android開發經常會用到handler,但是我們發現每次使用Handler都會出現:This Handler class should be static or leaks might occur(null)這樣的提示。Android lint就是為了提示我們,這樣使

Kotlin中handler避免記憶體洩漏

前言: Handler在Android開發中經常使用,一不小心就會陷入記憶體洩漏的問題,最近在開發一款Kotlin軟體,針對Handler記憶體洩漏的問題做出瞭解決方案 問題分析: 在fini

關於Android中的記憶體洩漏非同步操作

Android中記憶體洩漏是比較讓人頭痛的一塊問題,這兩天研究了下,放點乾貨吧,有時間再好好解析。 首先是如何檢查記憶體洩漏,這裡推薦使用square的leakCanary,絕對的神器。Github地址: 然後是一個自己寫的Demo,裡面有用到leakCanary進行記憶

Android Weak Handler:可以避免記憶體洩漏Handler

這是一個針對技術開發者的一個應用,你可以在掘金上獲取最新最優質的技術乾貨,不僅僅是Android知識、前端、後端以至於產品和設計都有涉獵,想成為全棧工程師的朋友不要錯過! android使用java作為其開發環境。java的跨平臺和垃圾回收機制已經幫助我們解決了底層的一些問題。但是儘管有了垃圾回收機

Android 記憶體洩漏LeakCanary

導言: 記憶體管理是android開發效能中重要的一環,而leakCanary是Square開源框架,是一個Android記憶體洩露檢測庫,是個優秀的 記憶體洩露檢測工具,通過它大大降低oom的出現,提高app的質量 釋義: 記憶體洩漏:物件在有限生命週期內還持有引用,沒有被回

Android使用Handler防止記憶體洩漏

在Android開發中經常會使用handler做定時任務或者更新UI等,但是handler在好用的同時也是非常容易導致記憶體洩漏。因為handler在作為一個類的屬性時會持有該類(通常是activity或fragment)的引用,而handler在傳送messa

Android 常見記憶體洩漏四大元凶

對於記憶體洩漏,我想大家應該都有碰到過,常見的表現就是異常程式退出。 到了程式強制關閉的時候,那已經到了一定的程度了。一般時候記憶體洩漏了我們是看不見的。因為它在堆中活動。 所以常常我們會通過一些工具來檢測。例如:LeakCanary、MAT等工具。 MAT是一款強大的記

C DataGridView所有行

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android O TextView記憶體洩漏

最近在版本迭代過程中遇到一個奇怪的記憶體洩漏問題,用mat開啟hprof檔案後,看到Activity例項還存在,檢視其gc root後,是這樣的結果: 可以看到是因為AsycTask引用了TextView,然後引用了EditText再引用了mContext,其

android效能優化——記憶體洩漏

在專案初期階段或者業務邏輯很簡單的時候對於app效能之一塊沒有太多感覺,但是隨著專案版本的迭代和專案業務邏輯越來越大,越來越複雜的時候,就會逐漸感覺到app效能的重要性,所以在專案初期階段時,就要有app效能這一意識,也便於專案後期的版本迭代和業務擴充套件;這裡所提到的效能優化問題是:記憶體洩漏

Android Studio檢查記憶體洩漏

1、前言 在Android Studio沒有出來之前,們普遍使用eclipse來進行開發,在開發的旅程中也會遇到發生記憶體洩漏的情況,我們可以利用MAT來進行記憶體檢測,查出具體導致記憶體洩漏的原因。而如今,這個時代已經成為歷史,在火遍全世界的今天,Android Studio成為了And

在 POSIX 執行緒程式設計中避免記憶體洩漏

POSIX 執行緒簡介 使用執行緒的主要原因是要提高程式效能。執行緒的建立和管理只需要較小的作業系統開銷和較少的系統資源。一個程序內的所有執行緒共享相同的地址空間,使得執行緒間的通訊更高效,且比程序間通訊更易於實現。例如,如果一個執行緒在等待一個輸入/輸出系統呼叫完成,其他執行緒可以處理 CPU 密集型任務

在JNI程式設計中避免記憶體洩漏(二)

JAVA 程式設計中的記憶體洩漏,從洩漏的記憶體位置角度可以分為兩種:JVM 中 Java Heap 的記憶體洩漏;JVM 記憶體中native memory 的記憶體洩漏。 Java 物件儲存在 JVM 程序空間中的 Java Heap 中,Java Heap 可以在 JVM 執行過程中動態變化。如果

Android面試總結 記憶體洩漏總結

記憶體管理的目的就是讓我們在開發中怎麼有效的避免我們的應用出現記憶體洩漏的問題。記憶體洩漏大家都不陌生了,簡單粗俗的講,就是該被釋放的物件沒有釋放,一直被某個或某些例項所持有卻不再被使用導致 GC 不能回收。 我會從 java 記憶體洩漏的基礎知識開始,並通過具體例子來

記憶體優化(二)如何避免記憶體洩漏

文章目錄 一、不同生命週期導致的記憶體洩漏 解決辦法 二、非靜態內部類持有物件導致的記憶體洩漏 1. 非靜態內部類呼叫外部類的方法的 2. 內部類是如

在 JNI 程式設計中避免記憶體洩漏與崩潰

JNI 程式設計簡介 JNI,Java Native Interface,是 native code 的程式設計介面。JNI 使 Java 程式碼程式可以與 native code 互動——在 Java 程式中呼叫 native code;在 native code 中

Android gc與記憶體洩漏,溢位的理解

GC介紹 在java中垃圾回收是自動釋放的,不像c/c++需要手動釋放,手動釋放可能處理不當, 會造成記憶體洩漏與資料混亂等等影響。 GC常用的回收演算法 1,計數 引用計數是垃圾收集器中的早期策略

用正確的姿勢來說說Android上的記憶體洩漏問題

相信大家對App的記憶體管理都是相當關心的,在專案上線前的幾天時間也會藉助相關工具突擊下嚴重的洩漏問題; 針對記憶體洩漏先提出幾個疑問: 什麼是記憶體洩漏? 記憶體洩漏帶來的危害又是什麼? 哪些程

c++避免記憶體洩漏

在c/c++語言對於程式記憶體的管理不像java語言一樣有自己的垃圾回收機制,而c/c++卻要程式設計師手動的釋放用關鍵字new或者 malloc系統函式申請的記憶體空間,然而由於程式設計師的疏忽可能

詳解java記憶體洩露和如何避免記憶體洩漏

源地址:http://www.xttblog.com/?p=518 一直以來java都佔據著語言排行榜的頭把交椅。這是與java的設計密不可分的,其中最令大家喜歡的不是面向物件,而是垃圾回收機制。你只需要簡單的建立物件而不需要負責釋放空間,因為Java的垃圾回收器會負責記憶