android.view.WindowLeaked: Activity
轉載請註明出處:https://blog.csdn.net/u011038298/article/details/84138185
記憶體洩露的原因:
當一個物件無需被使用時,應該被回收,但是當另外一個物件還持有對該物件的引用時,這樣就會導致該物件無法被GC回收,所以就會出現記憶體洩露的情況。
記憶體洩露場景一:
import android.app.Dialog; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; public class MainActivity extends AppCompatActivity { private Dialog mDialog; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化對話方塊 mDialog = new Dialog(this); View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_test, null); mDialog.setContentView(contentView); mDialog.setTitle("演示"); mDialog.show(); // 結束當前介面 finish(); } }
問題原因:當前activity被finish掉了,但是依附在當前activity的dialog卻沒有被關閉掉,造成記憶體洩露
解決方案:在activity的onDestory函式中加入判斷: if (mDialog!=null && mDialog.isShowing()) { mDialog.dismiss(); }
記憶體洩露場景二:
import android.content.Context; public class Test { private Context mContext; private static Test instance; private Test(Context context) { this.mContext = context; // 應該改為context.getApplicationContext() // this.mContext = context.getApplicationContext(); } public static Test getInstance(Context context) { if (instance != null) { instance = new Test(context); } return instance; } }
問題原因:當前activity被finish掉了,Context也會隨著Activity被銷燬,但是單例還持有該物件的引用,這時就會造成記憶體洩露。
解決方案:把context改為Application的Context,因為Application的Context生命週期跟隨著整個應用程式的生命週期。
記憶體洩露場景三:
import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandler.sendEmptyMessage(0); } }
問題原因:當使用內部類(包括匿名類)來建立Handler的時候,Handler物件會隱式地持有一個外部類物件(通常是一個Activity)的引用。如果activity被finish掉了,而handler還在工作的話,這時handler又持有Activity的引用,就導致該Activity無法被回收,造成記憶體洩露。
解決方案:可以在Activity的onDestroy()函式中呼叫Handler.removeCallbacksAndMessages(null); 也可以將Handler宣告為靜態類。在Java 中,非靜態的內部類和匿名內部類都會隱式地持有其外部類的引用,靜態的內部類不會持有外部類的引用。靜態類不持有外部類的物件,所以你的Activity可以隨意被回收。如果將Handler宣告為靜態類,請注意由於Handler不再持有外部類物件的引用,導致程式不允許你在Handler中操作Activity中的物件了,所以你需要在Handler中增加一個對Activity的弱引用。
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity {
private static class MyHandler extends Handler {
private WeakReference<MainActivity> mWeakReference;
public MyHandler(MainActivity activity) {
mWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final MainActivity activity = mWeakReference.get();
if (activity != null) {
switch (msg.what) {
case 0:
break;
}
}
}
}
private MyHandler mHandler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MyHandler(this);
mHandler.sendEmptyMessage(0);
}
}