欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

避免 Android中Context引起的內存泄露

 更新時間:2016年08月31日 17:34:34   作者:技術小黑屋  
本文主要介紹Android中Context引起的內存泄露的問題,這里對Context的知識做了詳細講解,說明如何避免內存泄漏的問題,有興趣的小伙伴可以參考下

Context是我們在編寫Android程序經常使用到的對象,意思為上下文對象。 常用的有Activity的Context還是有Application的Context。Activity用來展示活動界面,包含了很多的視圖,而視圖又含有圖片,文字等資源。在Android中內存泄露很容易出現,而持有很多對象內存占用的Activity更加容易出現內存泄露,開發(fā)者需要特別注意這個問題。

本文講介紹Android中Context,更具體的說是Activity內存泄露的情況,以及如何避免Activity內存泄露,加速應用性能。

Drawable引起的內存泄露

Drawable引起內存泄露這個問題是比較隱晦,難以察覺的。在閱讀了Romain Guy的Avoiding memory leaks,結合grepcode查看源碼才明白了。

在Android系統(tǒng)中,當我們進行了屏幕旋轉,默認情況下,會銷毀掉當前的Activity,并創(chuàng)建一個新的Activity并保持之前的狀態(tài)。在這個過程中,Android系統(tǒng)會重新加載程序的UI視圖和資源。假設我們有一個程序用到了一個很大的Bitmap圖像,我們不想每次屏幕旋轉時都重新加載這個Bitmap對象,最簡單的辦法就是將這個Bitmap對象使用static修飾。

private static 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);
}

但是上面的方法在屏幕旋轉時有可能引起內存泄露,無論是咋一看還是仔細看這段代碼,都很難發(fā)現哪里引起了內存泄露。

當一個Drawable綁定到了View上,實際上這個View對象就會成為這個Drawable的一個callback成員變量,上面的例子中靜態(tài)的sBackground持有TextView對象lable的引用,而lable只有Activity的引用,而Activity會持有其他更多對象的引用。sBackground生命周期要長于Activity。當屏幕旋轉時,Activity無法被銷毀,這樣就產生了內存泄露問題。

2.3.7及以下版本Drawable的setCallback方法的實現

public final void setCallback(Callback cb) {
 mCallback = cb;
}

好在從4.0.1開始,引入了弱引用處理這個問題,弱引用在GC回收時,不會阻止GC回收其指向的對象,避免了內存泄露問題。

public final void setCallback(Callback cb) {
 mCallback = new WeakReference<Callback>(cb);
}

單例引起的內存泄露

單例是我們比較簡單常用的一種設計模式,然而如果單例使用不當也會導致內存泄露。 比如這樣一個例子,我們使用餓漢式初始化單例,AppSettings我們需要持有一個Context作為成員變量,如果我們按照下面的實現其實是有問題。

public class AppSettings { 
 private Context mAppContext;
 private static AppSettings sInstance = new AppSettings();

 //some other codes
 public static AppSettings getInstance() {
  return sInstance;
 }
 
 public final void setup(Context context) {
  mAppContext = context;
 }
}

sInstance作為靜態(tài)對象,其生命周期要長于普通的對象,其中也包含Activity,當我們進行屏幕旋轉,默認情況下,系統(tǒng)會銷毀當前Activity,然后當前的Activity被一個單例持有,導致垃圾回收器無法進行回收,進而產生了內存泄露。

解決的方法就是不持有Activity的引用,而是持有Application的Context引用。代碼如下修改

public final void setup(Context context) {
 mAppContext = context.getApplicationContext(); 
}

訪問這里了解更多關于單例模式的問題

條條方法返回Context

通常我們想要獲取Context對象,主要有以下四種方法

  1. View.getContext,返回當前View對象的Context對象,通常是當前正在展示的Activity對象。
  2. Activity.getApplicationContext,獲取當前Activity所在的(應用)進程的Context對象,通常我們使用Context對象時,要優(yōu)先考慮這個全局的進程Context。
  3. ContextWrapper.getBaseContext():用來獲取一個ContextWrapper進行裝飾之前的Context,可以使用這個方法,這個方法在實際開發(fā)中使用并不多,也不建議使用。
  4. Activity.this 返回當前的Activity實例,如果是UI控件需要使用Activity作為Context對象,但是默認的Toast實際上使用ApplicationContext也可以。

其他內存泄露問題

Android中糟糕的AsyncTask

Android中Handler引起的內存泄露

OnSharedPreferenceChangeListener詳解及出現不觸發(fā)解決辦法

避免內存泄露須謹記

  1. 不要讓生命周期長于Activity的對象持有到Activity的引用
  2. 盡量使用Application的Context而不是Activity的Context
  3. 盡量不要在Activity中使用非靜態(tài)內部類,因為非靜態(tài)內部類會隱式持有外部類實例的引用(具體可以查看細話Java:”失效”的private修飾符了解)。如果使用靜態(tài)內部類,將外部實例引用作為弱引用持有。
  4. 垃圾回收不能解決內存泄露,了解Android中垃圾回收機制

參考文章

Avoiding memory leaks
Difference between getContext() , getApplicationContext() , getBaseContext() and “this”
Android – what's the difference between the various methods to get a Context?

以上就是對Android Context 內存泄漏的資料整理,后續(xù)繼續(xù)添加相關資料,謝謝大家的支持!

相關文章

  • Android之內置和外置sdcard路徑顯示并且寫入數據的方法

    Android之內置和外置sdcard路徑顯示并且寫入數據的方法

    今天小編就為大家分享一篇Android之內置和外置sdcard路徑顯示并且寫入數據的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • Android方向傳感器的使用方法

    Android方向傳感器的使用方法

    這篇文章主要介紹了Android方向傳感器的使用方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • Android仿微信朋友圈點擊評論自動定位到相關行功能

    Android仿微信朋友圈點擊評論自動定位到相關行功能

    這篇文章主要介紹了android仿微信朋友圈點擊評論自動定位到相關行功能的實現,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-05-05
  • android6.0運行時權限完美封裝方法

    android6.0運行時權限完美封裝方法

    今天小編就為大家分享一篇android6.0運行時權限完美封裝方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Android 工程內嵌資源文件的兩種方法

    Android 工程內嵌資源文件的兩種方法

    Android軟件一般處理大的資源通過sdcard比如在線下載資源到sdcard,而apk中內嵌資源或二進制文件時一般使用下面的兩種方法:
    2013-01-01
  • Android使用Handler實現View彈性滑動

    Android使用Handler實現View彈性滑動

    這篇文章主要介紹了Android使用Handler實現View彈性滑動,介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下
    2016-08-08
  • vscode通過wifi調試真機的Flutter應用的教程

    vscode通過wifi調試真機的Flutter應用的教程

    這篇文章主要介紹了vscode通過wifi調試真機的Flutter應用的教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • Android自定義view之太極圖的實現教程

    Android自定義view之太極圖的實現教程

    這篇文章主要給大家介紹了關于Android自定義view之太極圖的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • android獲取手機cpu并判斷是單核還是多核

    android獲取手機cpu并判斷是單核還是多核

    手機cpu是單核還是多核如何判斷,本例將會介紹android中獲取的方法,感興趣的你可不要錯過了哈
    2013-02-02
  • Android發(fā)送郵件的方法實例詳解

    Android發(fā)送郵件的方法實例詳解

    這篇文章主要介紹了Android發(fā)送郵件的方法,結合實例形式詳細分析了Android郵件發(fā)送的相關技巧與具體實現步驟,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-01-01

最新評論