當前位置:首頁 » 安卓系統 » android內存泄露解決

android內存泄露解決

發布時間: 2022-06-01 03:09:17

❶ Android中如何查找內存泄露

1、首先確定是否有內存泄露及哪個程序造成。
1.1、內存泄露已彈出out of memory對話框的情況。
這種情況很簡單,直接看對話框就知道是哪個應用的問題了。然後再分析該應用是否是因為內存泄露造成的
out of memory對話框。
》中介紹的各種方法進行分析,確定是否有內存泄露以及是哪個進程造成的內存泄露。
2、生成hprof文件,用MAT進行分析。
生成hprof文件可以在DDMS選中進程點擊窗口左上角的mp hprof file按鈕來直接生成,也可以通過在程序加代碼中來生成代碼2:voidgenerateHprof(){String packageName=getApplicationInfo().packageName;
StringhpFilePath=/data/data/+packageName+/input.hprof;try{//Debug.mpHprofData(/sdcard/input.hprof);Debug.
mpHprofData
(hpFilePath);}catch(IOException e) {//TODOAuto-generated catch block
e.printStackTrace();}}建議使用代碼生成hprof,然後使用《
Android內存泄露利器(hprof篇)》中的工具自動提取多個hprof文件,然後用MAT進行比較分析。在MAT導入.hprof文件以後,
MAT會自動解析並生成報告,點擊
Dominator Tree
,並按Package分組,選擇自己所定義的Package類,比較各個類在不同時期的RetainedHeap
,找出可疑類,然後選擇該類,點右鍵,選中
show retained Set項,參看Retained Heap
的詳細信息,進一步找出嫌疑項。
3、在代碼中查找內存泄露。
根據在MAT找到的內存泄露信息,參照《
Android內存泄漏簡介
》進一步在內存中查找內存泄露的原因並解決。
另外如果代碼很簡單,可以直接參照《
Android內存泄漏簡介
》在內存中查找內存泄露的原因並解決。

❷ android內存泄露怎樣解決

在Eclipse中新建一個Android工程,名字叫做:memoryleak。功能很簡單,只有一個MainActivity和一個ImageUtil。我們在MainActivity中使用ImageUtil來載入圖片。注意我們的ImageUtil是單例類。在創建的時候需要傳入context。

應用起來以後,轉屏。轉屏以後,MainActivity會重建,導致ImageUtil重新載入圖片。很不幸的是,因為ImageUtil並沒有重建,還持有之前的Context,也就是之前的那個MainActivity實例。多次轉屏以後,我們在Eclipse的DDMS裡面,導出內存映像文件。導出的文件叫做:com.example.memoryleak.hprof。

DDMS導出的內存映像文件並不能被MAT直接使用。需要轉換一下。在命令行輸入:hprof-conv com.example.memoryleak.hprof memoryleak.hprof。

用MAT打開memoryleak.hprof。

點擊「Histogram」
步驟閱讀
在Class Name後面的輸入框輸入應用的名字:com.example.memoryleak。

可以看到有4個MainActivity實例,如果沒有泄露的情況下只應該有一個實例,說明存在內存泄露。在MainActivity上點擊右鍵->"Merge
Shortest Paths To GC Roots"->"exclude all phantom/weak/soft
etc.refrences"。

8
在打開的頁面中,點擊可以看到詳細的引用信息。

9
上圖中可以看出來是ImageUtil引用了一個MainActivity的實例。這樣就找到了泄露的根源,就可以進行處理了。

❸ android內存泄露怎麼解決

從谷歌的Android 5.0.1系統開始,就有用戶反應存在內存泄漏問題,而在最新版本的Android 5.1更新來看,谷歌似乎並沒有解決這個問題,這讓許多用戶感到非常不滿。不過現在從谷歌的AOSP網站來看,似乎已經計劃著手解決這個問題,預計會在下次Android 5.1.1更新時到來。 最近包括許多用戶反映Android 5.1上Google+等應用會自動重啟,某些應用在使用時還會自動退出,導致內存佔用率大幅上升,大約會佔用750MB到800MB左右。還有用戶稱打開應用後內存佔用率會上升,但關掉應用後系統卻不會空出多餘內存。而目前許多Nexus 5用戶都表示遇到了這個問題。 看來,現在遇到內存泄漏問題的用戶還需要再耐性等待一段時間,等到谷歌發布Android 5.1.1更新才行了。

❹ androidstudio內存泄露怎麼辦

Android studio是沒有自帶這個工具的,不能分析內存泄露。需要用已經ROOT過的真機來獲取APP運行過程中的內存信息,這需要獲取該手機的最高許可權。如果沒有這樣的手機,或者沒有相應的機型,可以去testbird上面試試雲手機吧,上面的手機都是開放最高許可權的,而且機型很全。

❺ Android中如何防止內存溢出(摘)

但是Android採用的是java語言編寫,所以在很大程度上,Android的內存機制等同於Java的內存機制,在剛開始開發的時候,內存的限制問題會給我們帶來內存溢出等嚴重問題。在我們不使用一些內存的時候,我們要盡量在Android或者其他平台上避免在運行其他程序時,保存必要的狀態,使得一些死進程所帶來的內存問題,應該盡量在關閉程序或者保存狀態的時候釋放掉,這樣能提高系統在運行方面的流暢性。Android的內存主要表現在:1. 在Android平台上,長期保持一些資源的引用,造成一些內存不能釋放,帶來的內存泄露問題很多。比如:Context(下文中提到的Activity都是Context),在一些你需要保持你的首個類對象狀態,並且把狀態傳入其他類對象中時,這樣消除掉首個類對象之前,你必須先把接收類對象釋放掉。需要注意一點的是:因為在Java或者Android內存機制中,頂點的結點釋放前必須保證其他對象沒有調用才能被系統GC回收釋放。我們來看一段代碼: @Override protected void onCreate(Bundle state) { super.onCreate(state); TextViewlabel = new TextView(this); label.setText("Leaksare bad"); setContentView(label); }這個代碼的意思就是我們把一個TextView的實例載入到了我們正在運行的Activity(Context)當中,因此,通過GC回收機制,我們知道,要釋放Context,就必須先釋放掉引用他的一些對象。如果沒有,那在要釋放Context的時候,你會發現會有大量的內存溢出。所以在你不小心的情況下內存溢出是一件非常容易的事情。 保存一些對象時,同時也會造成內存泄露。最簡單的比如說點陣圖(Bitmap),比如說:在屏幕旋轉時,會破壞當前保持的一個Activity狀態,並且重新申請生成新的Activity,直到新的Activity狀態被保存。我們再看一段代碼: privatestatic Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground =getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); } 這個代碼是非常快的同時也是錯誤的。它的內存泄露很容易出在屏幕轉移的方向上。雖然我們會發現沒有顯示的保存Context這個實例,但是當我們把繪制的圖連接到一個視圖的時候,Drawable就會將被View設置為回調,這就說明,在上述的代碼中,其實在繪制TextView到活動中的時候,我們已經引用到了這個Activity。鏈接情況可以表現為:Drawable->TextView->Context。所以在想要釋放Context的時候,其實還是保存在內存中,並沒有得到釋放。如何避免這種情況:主要在於。線程最容易出錯。大家不要小看線程,在Android裡面線程最容易造成內存泄露。線程產生內存泄露的主要原因在於線程生命周期的不可控。下面有一段代碼:publicclass MyTest extends Activity { @Override publicvoid onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new MyThread().start(); } privateclass MyThread extends Thread{ @Override public void run() { super.run(); //do somthing } } } 代碼很簡單,但是在Android上又來新問題了,當我們在切換視圖屏幕的時候(橫豎屏),就會重新建立橫屏或者豎屏的Activity。我們形象的認為之前建立的Activity會被回收,但是事實如何呢?Java機制不會給你同樣的感受,在我們釋放Activity之前,因為run函數沒有結束,這樣MyThread並沒有銷毀,因此引用它的Activity(Mytest)也有沒有被銷毀,因此也帶來的內存泄露問題。有些人喜歡用Android提供的AsyncTask,但事實上AsyncTask的問題更加嚴重,Thread只有在run函數不結束時才出現這種內存泄露問題,然而AsyncTask內部的實現機制是運用了ThreadPoolExcutor,該類產生的Thread對象的生命周期是不確定的,是應用程序無法控制的,因此如果AsyncTask作為Activity的內部類,就更容易出現內存泄露的問題。線程問題的改進方式主要有:(1) 將線程的內部類,改為靜態內部類。(2) 在程序中盡量採用弱引用保存Context。 2. BitmapBitmap是一個很萬惡的對象,對於一個內存對象,如果該對象所佔內存過大,在超出了系統的內存限制時候,內存泄露問題就很明顯了。。解決bitmap主要是要解決在內存盡量不保存它或者使得采樣率變小。在很多場合下,因為我們的圖片像素很高,而對於手機屏幕尺寸來說我們並不用那麼高像素比例的圖片來載入時,我們就可以先把圖片的采樣率降低在做原來的UI操作。如果在我們不需要保存bitmap對象的引用時候,我們還可以用軟引用來做替換。具體的實例代碼google上面也有很多。綜上所述,要避免內存泄露,主要要遵循以下幾點:第一:不要為Context長期保存引用(要引用Context就要使得引用對象和它本身的生命周期保持一致)。第二:如果要使用到Context,盡量使用ApplicationContext去代替Context,因為ApplicationContext的生命周期較長,引用情況下不會造成內存泄露問題。第三:在你不控制對象的生命周期的情況下避免在你的Activity中使用static變數。盡量使用WeakReference去代替一個static。 A obj = new A(); WeakReference wr = new WeakReference(obj); obj = null; 這是一個簡單的弱引用的例子,簡單來說就是回收那些NULL值對象所佔的內存空間。 java與C系列語言不同之一就是內存操作都是由後台進行的,其中System.gc()方法可以回收內存。 比如你使用了一個BITMAP,在使用之後馬上讓它的值為NULL,這個BITMAP用過的內存就會被gc回收(也可以直接加上System.gc()快速回收),從而達到利用弱引用來緩解內存溢出的目的。 )第四:垃圾回收器並不保證能准確回收內存,這樣在使用自己需要的內容時,主要生命周期和及時釋放掉不需要的對象。盡量在Activity的生命周期結束時,在onDestroy中把我們做引用的其他對象做釋放,比如:cursor.close()。 其實我們可以在很多方面使用更少的代碼去完成程序。比如:我們可以多的使用9patch圖片等。有很多細節地方都可以值得我們去發現、挖掘更多的內存問題。

❻ 導致android內存泄漏原因有哪些

Android應用內存泄漏的的原因有以下幾個:
1查詢資料庫後沒有關閉游標cursor
2 構造Adapter時,沒有使用 convertView 重用
3 Bitmap對象不在使用時調用recycle()釋放內存
4 對象被生命周期長的對象引用,如activity被靜態集合引用導致activity不能釋放

內存泄漏的發現:
通過DDMS中的heap工具,去發現是否有內存溢出。

內存泄漏如何解決:
通過內存分析工具 MAT(Memory Analyzer Tool),找到內存泄露的對象

❼ android scrollview內存溢出怎麼解決

android scrollview內存溢出通常是由內存泄露導致。
1、內存泄露導致
由於我們程序的失誤,長期保持某些資源(如Context)的引用,垃圾回收器就無法回收它,當然該對象佔用的內存就無法被使用,這就造成內存泄露。
Android 中常見就是Activity被引用在調用finish之後卻沒有釋放,第二次打開activity又重新創建,這樣的內存泄露不斷的發生,則會導致內存的溢出。
Android的每個應用程序都會使用一個專有的Dalvik虛擬機實例來運行,它是由Zygote服務進程孵化出來的,也就是說每個應用程序都是在屬於自己的進程中運行的。Android為不同類型的進程分配了不同的內存使用上限,如果程序在運行過程中出現了內存泄漏的而造成應用進程使用的內存超過了這個上限,則會被系統視為內存泄漏,從而被kill掉,這使得僅僅自己的進程被kill掉,而不會影響其他進程.
2、佔用內存較多的對象
保存了多個耗用內存過大的對象(如Bitmap)或載入單個超大的圖片,造成內存超出限制。
使用方法比較簡單:
· 選擇DDMS視圖,並打開Devices視圖和Heap視圖
· 點擊選擇要監控的進程,比如:上圖中我選擇的是system_process
· 選中Devices視圖界面上的"update heap" 圖標
· 點擊Heap視圖中的"Cause GC" 按鈕(相當於向虛擬機發送了一次GC請求的操作)
在Heap視圖中選擇想要監控的Type,一般我們會觀察dataobject的 total size的變化,正常情況下total size的值會穩定在一個有限的范圍內,也就說程序中的代碼良好,沒有造成程序中的對象不被回收的情況。如果代碼中存在沒有釋放對象引用的情況,那麼data object的total size在每次GC之後都不會有明顯的回落,隨著操作次數的增加而total size也在不斷的增加。(說明:選擇好data object後,不斷的操作應用,這樣才可以看出total size的變化)。如果totalsize確實是在不斷增加而沒有回落,說明程序中有沒有被釋放的資源引用。那麼我們應該怎麼來定位呢?
Android中內存泄露定位
通過DDMS工具可以判斷應用程序中是否存在內存泄漏的問題,那又如何定位到具體出現問題的代碼片段,最終找到問題所在呢?內存分析工具MAT Memory Analyzer Tool解決了這一難題。MAT工具是一個Eclipse 插件,同時也有單獨的RCP 客戶端,MAT工具的解析文件是.hprof,這個文件存放了某進程的內存快照。MAT工具定位內存泄漏具體位置的方法如下:
① 生成.hprof文件。Eclipse中生成.hprof文件的方法有很多,不同Android版本中生成.hprof的方式也稍有差別,但它們整體思路是一樣的。我們在DDMS界面選中想要分析的應用進程,在Devices視圖界面上方的一行圖標按鈕中,同時選中「Update Heap」和「Dump HPROF file」兩個按鈕,這時DDMS將會自動生成當前選中進程的.hprof文件。
② 將.hprof 文件導入到MAT工具中,MAT工具會自動解析並生成報告,點擊「Dominator Tree」按鈕,並按包分組,選擇已定義的包類點右鍵,在彈出的菜單中選擇List objects﹥With incoming references,這時會列出所有可疑的類。右鍵點擊某一項,並選擇Path to GC Roots﹥excludeweak/soft references,MAT工具會進一步篩選出跟程序相關的所有內存泄漏的類。這樣就可以追蹤到某一個產生內存泄漏的類的具體代碼中。
使用MAT內存分析工具查找內存泄漏的根本思路是找到哪個類的對象的引用沒有被釋放,然後分析沒有被釋放的原因,最終定位到代碼中哪些片段存在著內存泄漏。

❽ 9,android內存泄露發生的場景有哪些有什麼對應的解決方案

1.查詢資料庫而沒有關閉Cursor
在Android中,Cursor是很常用的一個對象,但在寫代碼是,經常會有人忘記調用close, 或者因為代碼邏輯問題狀況導致close未被調用。

通常,在Activity中,我們可以調用startManagingCursor或直接使用managedQuery讓Activity自動管理Cursor對象。
但需要注意的是,當Activity介紹後,Cursor將不再可用!
若操作Cursor的代碼和UI不同步(如後台線程),那沒需要先判斷Activity是否已經結束,或者在調用OnDestroy前,先等待後台線程結束。

除此之外,以下也是比較常見的Cursor不會被關閉的情況:

1.try {
2. Cursor c = queryCursor();
3. int a = c.getInt(1);
4. ......
5. c.close();
6.} catch (Exception e) {
7.}
雖然表面看起來,Cursor.close()已經被調用,但若出現異常,將會跳過close(),從而導致內存泄露。
所以,我們的代碼應該以如下的方式編寫:

01.Cursor c = queryCursor();
02.try {
03. int a = c.getInt(1);
04. ......
05.} catch (Exception e) {
06.} finally {
07. c.close(); //在finally中調用close(), 保證其一定會被調用
08.}

2.調用registerReceiver後未調用unregisterReceiver().
在調用registerReceiver後,若未調用unregisterReceiver,其所佔的內存是相當大的。
而我們經常可以看到類似於如下的代碼:

01.registerReceiver(new BroadcastReceiver() {
02. ...
03.}, filter); ...
這是個很嚴重的錯誤,因為它會導致BroadcastReceiver不會被unregister而導致內存泄露。

3.未關閉InputStream/OutputStream

在使用文件或者訪問網路資源時,使用了InputStream/OutputStream也會導致內存泄露

4.Bitmap使用後未調用recycle()
根據SDK的描述,調用recycle並不是必須的。但在實際使用時,Bitmap佔用的內存是很大的,所以當我們不再使用時,盡量調用recycle()以釋放資源。

5.Context泄露

這是一個很隱晦的內存泄露的情況。
先讓我們看一下以下代碼:
01.private static Drawable sBackground;
02.
03.@Override
04.protected void onCreate(Bundle state) {
05. super.onCreate(state);
06.
07. TextView label = new TextView(this);
08. label.setText("Leaks are bad");
09.
10. if (sBackground == null) {
11. sBackground = getDrawable(R.drawable.large_bitmap);
12. }
13. label.setBackgroundDrawable(sBackground);
14.
15. setContentView(label);
16.}
在這段代碼中,我們使用了一個static的Drawable對象。
這通常發生在我們需要經常調用一個Drawable,而其載入又比較耗時,不希望每次載入Activity都去創建這個Drawable的情況。
此時,使用static無疑是最快的代碼編寫方式,但是其也非常的糟糕。
當一個Drawable被附加到View時,這個View會被設置為這個Drawable的callback (通過調用Drawable.setCallback()實現)。
這就意味著,這個Drawable擁有一個TextView的引用,而TextView又擁有一個Activity的引用。
這就會導致Activity在銷毀後,內存不會被釋放。

❾ android開發什麼叫內存泄露

下面圖片是解決內存泄露的例子。例子來自android學習手冊,android學習手冊,裡面有源碼。android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼

在android程序開發中,當一個對象已經不需要再使用了,本該被回收時,而另外一個正在使用的對象持有它的引用從而導致它不能被回收,這就導致本該被回收的對象不能被回收而停留在堆內存中,內存泄漏就產生了。

內存泄漏有什麼影響呢?它是造成應用程序OOM的主要原因之一。由於android系統為每個應用程序分配的內存有限,當一個應用中產生的內存泄漏比較多時,就難免會導致應用所需要的內存超過這個系統分配的內存限額,這就造成了內存溢出而導致應用Crash。

了解了內存泄漏的原因及影響後,我們需要做的就是掌握常見的內存泄漏,並在以後的android程序開發中,盡量避免它。下面小編搜羅了5個android開發中比較常見的內存泄漏問題及解決辦法,分享給大家,一起來看看吧。

一、單例造成的內存泄漏

Android的單例模式非常受開發者的喜愛,不過使用的不恰當的話也會造成內存泄漏。因為單例的靜態特性使得單例的生命周期和應用的生命周期一樣長,這就說明了如果一個對象已經不需要使用了,而單例對象還持有該對象的引用,那麼這個對象將不能被正常回收,這就導致了內存泄漏。

如下這個典例:

public class AppManager {

private static AppManager instance;

private Context context;

private AppManager(Context context) {

this.context = context;

}

public static AppManager getInstance(Context context) {

if (instance != null) {

instance = new AppManager(context);

}

return instance;

}

}

這是一個普通的單例模式,當創建這個單例的時候,由於需要傳入一個Context,所以這個Context的生命周期的長短至關重要:

1、傳入的是Application的Context:這將沒有任何問題,因為單例的生命周期和Application的一樣長 ;

2、傳入的是Activity的Context:當這個Context所對應的Activity退出時,由於該Context和Activity的生命周期一樣長(Activity間接繼承於Context),所以當前Activity退出時它的內存並不會被回收,因為單例對象持有該Activity的引用。

所以正確的單例應該修改為下面這種方式:

public class AppManager {

private static AppManager instance;

private Context context;

private AppManager(Context context) {

this.context = context.getApplicationContext();

}

public static AppManager getInstance(Context context) {

if (instance != null) {

instance = new AppManager(context);

}

return instance;

}

}

這樣不管傳入什麼Context最終將使用Application的Context,而單例的生命周期和應用的一樣長,這樣就防止了內存泄漏。

二、非靜態內部類創建靜態實例造成的內存泄漏

有的時候我們可能會在啟動頻繁的Activity中,為了避免重復創建相同的數據資源,會出現這種寫法:

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 {

//...

}

}

這樣就在Activity內部創建了一個非靜態內部類的單例,每次啟動Activity時都會使用該單例的數據,這樣雖然避免了資源的重復創建,不過這種寫法卻會造成內存泄漏,因為非靜態內部類默認會持有外部類的引用,而又使用了該非靜態內部類創建了一個靜態的實例,該實例的生命周期和應用的一樣長,這就導致了該靜態實例一直會持有該Activity的引用,導致Activity的內存資源不能正常回收。正確的做法為:

將該內部類設為靜態內部類或將該內部類抽取出來封裝成一個單例,如果需要使用Context,請使用ApplicationContext 。

三、Handler造成的內存泄漏

Handler的使用造成的內存泄漏問題應該說最為常見了,平時在處理網路任務或者封裝一些請求回調等api都應該會藉助Handler來處理,對於Handler的使用代碼編寫一不規范即有可能造成內存泄漏,如下示例:

public class MainActivity extends AppCompatActivity {

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

//...

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

loadData();

}

private void loadData(){

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

}

這種創建Handler的方式會造成內存泄漏,由於mHandler是Handler的非靜態匿名內部類的實例,所以它持有外部類Activity的引用,我們知道消息隊列是在一個Looper線程中不斷輪詢處理消息,那麼當這個Activity退出時消息隊列中還有未處理的消息或者正在處理消息,而消息隊列中的Message持有mHandler實例的引用,mHandler又持有Activity的引用,所以導致該Activity的內存資源無法及時回收,引發內存泄漏,所以另外一種做法為:

public class MainActivity extends AppCompatActivity {

private MyHandler mHandler = new MyHandler(this);

private TextView mTextView ;

private static class MyHandler extends Handler {

private WeakReference<Context> reference;

public MyHandler(Context context) {

reference = new WeakReference<>(context);

}

@Override

public void handleMessage(Message msg) {

MainActivity activity = (MainActivity) reference.get();

if(activity != null){

activity.mTextView.setText("");

}

}

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView)findViewById(R.id.textview);

loadData();

}

private void loadData() {

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

}

創建一個靜態Handler內部類,然後對Handler持有的對象使用弱引用,這樣在回收時也可以回收Handler持有的對象,這樣雖然避免了Activity泄漏,不過Looper線程的消息隊列中還是可能會有待處理的消息,所以我們在Activity的Destroy時或者Stop時應該移除消息隊列中的消息,更准確的做法如下:

public class MainActivity extends AppCompatActivity {

private MyHandler mHandler = new MyHandler(this);

private TextView mTextView ;

private static class MyHandler extends Handler {

private WeakReference<Context> reference;

public MyHandler(Context context) {

reference = new WeakReference<>(context);

}

@Override

public void handleMessage(Message msg) {

MainActivity activity = (MainActivity) reference.get();

if(activity != null){

activity.mTextView.setText("");

}

}

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView)findViewById(R.id.textview);

loadData();

}

private void loadData() {

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

@Override

protected void onDestroy() {

super.onDestroy();

mHandler.removeCallbacksAndMessages(null);

}

}

使用mHandler.removeCallbacksAndMessages(null);是移除消息隊列中所有消息和所有的Runnable。當然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();來移除指定的Runnable和Message。

四、線程造成的內存泄漏

對於線程造成的內存泄漏,也是平時比較常見的,如下這兩個示例可能每個人都這樣寫過:

//——————test1

new AsyncTask<Void, Void, Void>() {

@Override

protected Void doInBackground(Void... params) {

SystemClock.sleep(10000);

return null;

}

}.execute();

//——————test2

new Thread(new Runnable() {

@Override

public void run() {

SystemClock.sleep(10000);

}

}).start();

上面的非同步任務和Runnable都是一個匿名內部類,因此它們對當前Activity都有一個隱式引用。如果Activity在銷毀之前,任務還未完成, 那麼將導致Activity的內存資源無法回收,造成內存泄漏。正確的做法還是使用靜態內部類的方式,如下:

static class MyAsyncTask extends AsyncTask<Void, Void, Void> {

private WeakReference<Context> weakReference;

public MyAsyncTask(Context context) {

weakReference = new WeakReference<>(context);

}

@Override

protected Void doInBackground(Void... params) {

SystemClock.sleep(10000);

return null;

}

@Override

protected void onPostExecute(Void aVoid) {

super.onPostExecute(aVoid);

MainActivity activity = (MainActivity) weakReference.get();

if (activity != null) {

//...

}

}

}

static class MyRunnable implements Runnable{

@Override

public void run() {

SystemClock.sleep(10000);

}

}

//——————

new Thread(new MyRunnable()).start();

new MyAsyncTask(this).execute();

這樣就避免了Activity的內存資源泄漏,當然在Activity銷毀時候也應該取消相應的任務AsyncTask::cancel(),避免任務在後台執行浪費資源。

五、資源未關閉造成的內存泄漏

對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,造成內存泄漏。

❿ android 怎樣處理內存泄露

在用java開發android,activity,service,對象生存周期參看官方文檔,在不存在內部類給外部使用時,或者靜態內部類,結束時不用管,super.onDestroy()後肯定回收了;如果在本activity(or server )結束應該被回收了,還被外部持有一個其context的對象,就會導致不能回收。不過這樣的MemoryLeak在引用結束後也能回收的,單進程多線程,比如裡面使用了Runnalbe,其周期也不超過Application。如果你自己重寫了Application類,注意下引用。c/c++ 的NDK開發,以及驅動開發,推薦qq40289072答案

熱點內容
手機如何給u盤加密 發布:2025-08-20 12:56:30 瀏覽:671
自動更新源碼 發布:2025-08-20 12:48:36 瀏覽:743
已關聯的qq為什麼還要驗證密碼 發布:2025-08-20 12:46:01 瀏覽:814
c語言vector用法 發布:2025-08-20 12:46:00 瀏覽:460
lol腳本代練封號 發布:2025-08-20 12:44:39 瀏覽:57
時空幻境安卓版哪裡有 發布:2025-08-20 12:43:43 瀏覽:288
解壓摳畫妝 發布:2025-08-20 12:41:34 瀏覽:844
華彩人生電腦版無法連接伺服器 發布:2025-08-20 12:26:41 瀏覽:984
xp腳本錯誤 發布:2025-08-20 12:11:19 瀏覽:845
租用伺服器有什麼優勢 發布:2025-08-20 12:06:32 瀏覽:871