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); }
如上這段代碼,context的內存泄露通常很隱蔽,但基本上是與靜態變量相關的,如上代碼中,TextView使用了靜態對象sBackground,在框架中,TextView對象會經過callback的形式回傳給sBackground,而TextView對象引用了Context實例,這就致使了當Activity調用onDestroy關閉的時候,Activity內存不會被銷燬,而是直到靜態變量sBackground被回收的時候纔會銷燬。從而引發了context的內存泄露。java
這個泄露問題在android3.0以後已被修復,由於3.0開始callback使用了弱引用保存對象。android
還有一個隱藏的context內存泄露以下:框架
public class MainActivity extends Activity{ static Demo sInstance = null; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(sInstance == null){ sInstance = new Demo(); } } class Demo{ void doSomething(){ } } }
因爲內部類會持有外部類的實例,所以如上的靜態變量sInstance依然會引發context內存泄露。ide
另一個常見的context泄露在於系統Service,咱們在使用系統service的時候一般會傳遞給service當前activity的實例context,然而若是系統service自己持有靜態變量,而靜態變量又引用了context實例的話就會致使泄露。測試
private static Context serviceContext = null; private static ColorManagerListener colorMgrListener; public static int connect(Context context, ColorManagerListener colorListener) { if ((context == null) || (colorListener == null)) { Log.e(TAG, "One of the parmeter passed is null"); return -904; } colorMgrListener = colorListener; serviceContext = context;
上面的代碼段是第三方公司的service提供給咱們的jar包,測試發現有context內存泄露。反編譯jar包後發現serviceContext和colorMgrListener這兩個靜態變量直接持有了context對象,會致使context的內存泄露。this