內存泄漏
內存泄漏一般有以下幾種情況:單例、靜態變量、Handler、匿名內部類、資源使用未關閉
單例導致的內存泄漏
單例的情況主要是因為單例的生命周期比較長,如果引用的一些資源(比如Context、圖片等)沒有做特殊處理,就容易導致內存泄漏。具體的分析可以查看文章:Android 單例模式的正確姿勢
靜態變量導致的內存泄漏
靜態變量的生命周期同樣很長,如果引用了一些資源沒有及時釋放的話就會導致內存泄漏,比如Context、圖片的引用等。
引用圖片資源,這樣寫就要小心了。
private static LinkedHashMap<String, Bitmap> mapPool;
引用的是Context,比如Activity。
public class MyActivity extends AppCompatActivity {
private static MyClass myClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (myClass == null) {
myClass = new MyClass(this);
}
}
class MyClass {
MyClass(Activity activity) {
}
}
}
Activity退出后myClass仍然持有Activity的引用導致Activity無法被回收。
Handler導致的內存泄漏
Handler導致的內存泄漏需要先充分理解Android的消息機制,其中跟內存泄漏有關的一個點就是消息Message會持有Handler引用,這樣的話如果消息隊列中有消息還沒有處理完的話,Handler就無法釋放,這個時候如果Handler里面還引用了Activity或是其他資源,那就會導致內存泄漏。
一種情況是Handler是內部類,由于內部類會默認引用外部類,這時候如果外部是Activity等,就可能造成內存泄漏
public class MainActivity extends AppCompatActivity {
private static LinkedHashMap<String, Bitmap> mapPool;
private class MyHandler extends Handler {
@Override
public void handleMessage(Message message) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
解決方式也簡單,就是將Handler定義為靜態內部類。當然如果Handler里面還顯示引用了Context或是View等資源,最好用弱引用。
匿名內部類
匿名內部類導致的內存泄漏原因是匿名內部類會默認引用外部類,如果外部類是Activity等資源型類的話就會導致內存泄漏。所以你看我們通過自動工具生成的一些類,比如我們用GsonFormat生成的實體Bean,內部類都是靜態的。
資源使用未關閉
資源使用未關閉這個比較好理解,常見的資源類型有廣播BraodcastReceiver、ContentObserver、File、數據庫游標Cursor、以及Stream和Bitmap。在使用這些資源時我們就需要注意在不使用的時候需要及時釋放這些資源。
系統bug導致的內存泄漏
這種情況不用檢測工具很難發現,比如LeakCanary。這里就記錄一個InputMethodManager導致的內存泄漏。具體情形和解決方法可以查看文章:Android InputMethodManager內存泄漏 解決方法總結
感謝塵封的落葉的提醒。
歡迎關注我的微信公眾號,和我一起每天進步一點點!