1.數據庫的cursor沒有關閉。
2.構造adapter沒有使用緩存contentview。
3.調用registerReceiver後未調用unregisterReceiver()。
4.未關閉InputStream/OutputStream。
5.Bitmap使用後未調用recycle()。
6.Context泄漏。
前5種情況容易發現和解決,只要把該關的及時關閉,該調用的方法及時調用,就不會有太多問題,另外java裏還有軟引用幫助管理內存:
SoftReference<Bitmap> bitmap;
bitmap = new SoftReference<Bitmap>(pBitmap);
if(bitmap != null){
if(bitmap.get() != null && !bitmap.get().isRecycled()){
bitmap.get().recycle();
bitmap = null;
}
}
下面着重介紹Context泄漏。
這是一個很隱晦的內存泄露的情況。先看一個Android官網提供的例子:
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); }
這段代碼效率很快,但同時又是極其錯誤的;在第一次屏幕方向切換時它泄露了一開始創建的Activity。當一個Drawable附加到一個View上時,View會將其作爲一個callback設定到Drawable上。上述的代碼片段,意味着Drawable擁有一個TextView的引用,而TextView又擁有Activity(Context類型)的引用,換句話說,Drawable擁有了更多的對象引用。即使Activity被銷燬,內存仍然不會被釋放。
另外,對Context的引用超過它本身的生命週期,也會導致Context泄漏。所以儘量使用Application這種Context類型。這種Context擁有和應用程序一樣長的生命週期,並且不依賴Activity的生命週期。如果你打算保存一個長時間的對象,並且其需要一個Context,記得使用Application對象。你可以通過調用Context.getApplicationContext()或Activity.getApplication()輕鬆得到Application對象。
最近遇到一種情況引起了Context泄漏,就是在Activity銷燬時,裏面有其他線程沒有停。
總結一下避免Context泄漏應該注意的問題:
1.使用Application這種Context類型。
2.注意對Context的引用不要超過它本身的生命週期。
3.慎重的使用“static”關鍵字。
4.Context裏如果有線程,一定要在onDestroy()裏及時停掉。