編輯:關於Android編程
Context是我們在編寫Android程序經常使用到的對象,意思為上下文對象。 常用的有Activity的Context還是有Application的Context。Activity用來展示活動界面,包含了很多的視圖,而視圖又含有圖片,文字等資源。在Android中內存洩露很容易出現,而持有很多對象內存占用的Activity更加容易出現內存洩露,開發者需要特別注意這個問題。
本文講介紹Android中Context,更具體的說是Activity內存洩露的情況,以及如何避免Activity內存洩露,加速應用性能。
Drawable引起的內存洩露
Drawable引起內存洩露這個問題是比較隱晦,難以察覺的。在閱讀了Romain Guy的Avoiding memory leaks,結合grepcode查看源碼才明白了。
在Android系統中,當我們進行了屏幕旋轉,默認情況下,會銷毀掉當前的Activity,並創建一個新的Activity並保持之前的狀態。在這個過程中,Android系統會重新加載程序的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); }
但是上面的方法在屏幕旋轉時有可能引起內存洩露,無論是咋一看還是仔細看這段代碼,都很難發現哪裡引起了內存洩露。
當一個Drawable綁定到了View上,實際上這個View對象就會成為這個Drawable的一個callback成員變量,上面的例子中靜態的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作為靜態對象,其生命周期要長於普通的對象,其中也包含Activity,當我們進行屏幕旋轉,默認情況下,系統會銷毀當前Activity,然後當前的Activity被一個單例持有,導致垃圾回收器無法進行回收,進而產生了內存洩露。
解決的方法就是不持有Activity的引用,而是持有Application的Context引用。代碼如下修改
public final void setup(Context context) { mAppContext = context.getApplicationContext(); }
訪問這裡了解更多關於單例模式的問題
條條方法返回Context
通常我們想要獲取Context對象,主要有以下四種方法
其他內存洩露問題
Android中糟糕的AsyncTask
Android中Handler引起的內存洩露
OnSharedPreferenceChangeListener詳解及出現不觸發解決辦法
避免內存洩露須謹記
參考文章
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 內存洩漏的資料整理,後續繼續添加相關資料,謝謝大家的支持!
我在開發的時候遇到了這樣的需求,就是在listview的滑動中,需要對頂部的欄目由透明慢慢的變為不透明的狀態,就是以下的效果最先開始的時候想的很簡單,無非就是監聽list
感覺RxJava最近風生水起,不學習一下都不好意思了,灑家也是初學RxJava,也是感覺代碼好像更復雜更難懂了,看了一篇外文感同身受,簡單翻譯一下。本文簡單介紹使用Rx
之前也試過vitamio這個庫,後來不知道被什麼事情給耽擱了,就沒繼續下去。近來覺得視頻還是需要學習一下的,誰讓直播那麼火呢,就想著寫一個簡單的視頻播放的app先吧。好了
前文介紹了Android中MediaPlayer用法的時候稍微介紹了SurfaceView,SurfaceView由於可以直接從內存或者DMA等硬件接口取得圖像數據,因此