如果是想認真學習的話,請先不要看以下內容,此記錄只是爲加深記憶,可能會有錯誤的地方,以免有誤導。
學習轉載鏈接:https://blog.csdn.net/u014674558/article/details/62234008
App常見內存泄漏以及解決方法
1、非靜態內部類,靜態實例化
/**
* 自定義實現的Activity
*/
public class MyActivity extends AppCompatActivity {
/**
* 靜態成員變量
*/
public static InnerClass innerClass = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
innerClass = new InnerClass();
}
class InnerClass {
public void doSomeThing() {
}
}
}
內部類InnerClass隱式持有外部類MyActivity的引用,在MyActivity的onCreate方法中調用innerClass = new InnerClass();
innerClass會在MyActivity創建的時候就有了它的引用,而innerclass是靜態類型,不會被垃圾回收,MyActivity在執行onDestory方法的時候由於被innerClass持有引用而無法被回收,所以這樣MyActivity就總是被innerClass持有而無法回收造成內存泄漏
2、不正確的使用Context對象,造成內存泄漏
比如在Android幫助類中,會有很多引用Context
/**
* 自定義單例對象
*/
public class Single {
private static Single instance;
private Context context;
private Object obj = new Object();
private Single(Context context) {
this.context = context;
}
/**
* 初始化獲取單例對象
*/
public static Single getInstance(Context context) {
if (instance == null) {
synchronized(obj) {
if (instance == null) {
instance = new Single(context);
}
}
}
return instance;
}
}
解決方法:使用全局的Context或者context.getApplication();
3、使用handler異步消息通信
日常開發中我們通常這樣定義Handler對象:
/**
* 定義Handler成員變量
*/
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
dosomething();
}
};
這樣存在一個隱藏問題:在Activity中使用Handler創建的匿名內部類會隱式持有外部Activity對象,當子線程使用Handler暫時無法完成異步任務時,handler對象無法銷燬,同時隱式持有的activity以及相關的組件與資源文件同樣無法銷燬,在成內存泄漏。我們普通的handler,平時使用時也是可以不用考慮這些,但是在子線程中有耗時操作通知UI時,要考慮這一點
解決方法:
使用靜態變量定義handler,靜態變量無法操作activity中的對象,所以需要在handler對象中添加一個對activity的弱引用
static MyHandler handler = new MyHandler (this) {
@Override
public void handleMessage(Message msg) {
dosomething();
}
};
static class MyHandler extends Handler {
WeakReference<Activity > mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
最後在onDestory方法中將後面的消息移除 handler.removeCallbackAndMessages(null);
4、使用了屬性屬性動畫或循環動畫
在Activity中使用了屬性循環動畫,在onDestory()方法中未正確停止動畫
5、使用資源文件結束之後未關閉
在使用一些資源性對象(比如Cusor,File,Stream,ContentProvider等)往往都用了一些緩衝,我們在不使用的時候,應該及時關閉它們,以便它們的緩衝及時回收內存,它們的緩衝不僅存在於java虛擬機中,還存在與java虛擬機外。如果我們僅僅是把它們設置爲null,而不去close關閉,仍然會造成內存泄漏
6、Bitmap使用不當
bitmap對象使用的內存比較大,當我們不再使用bitmap對象的時候一定要執行recycle方法,執行該方法不會立即釋放掉,只是通知虛擬機該bitmap可以被recycle了
7、一些框架使用了註冊方法而未反註冊
比如我們常用的時間總線框架-EventBus,當我們需要註冊某個Activity時,需要在onCreate中:
EventBus.getDefault().register(this);
則EventBus對象持有該Activity的引用,及時onDestory,仍然無法回收,需要在onDestory方法中調用
EventBus.getDefault().unregister(this);
8、集合中的一些方法的錯誤使用
比如list列表靜態化,只是添加元素而不再使用時不清除元素;
map對象只是put,沒有remove操作等;