内存泄露的原因:
当一个对象无需被使用时,应该被回收,但是当另外一个对象还持有对该对象的引用时,这样就会导致该对象无法被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);
}
}