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);
    }

}

猜你喜欢

转载自blog.csdn.net/u011038298/article/details/84138185