android常见内存泄漏

无人久伴 提交于 2020-02-20 09:09:29

1、静态变量

类中定义了静态Activity变量,把当前的Activity赋值给静态变量,如果Activity生命周期结束的时候静态变量没有清空,就会导致内存泄漏。static变量是贯穿整个应用的生命周期,所以被泄漏的Activity就会一直存在于应用的进程中,不会被回收。

private static Activity sActivity;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        sActivity = this;
        findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

    }
}

2、非静态内部类创建静态实例

这里的非静态内部类是Config,创建的静态实例是sConfig

造成内存泄漏的原因是内部类会隐式持有外部类的引用,这里的外部类是NonStaticActivity,然而内部类sConfig又是static静态变量,其生命周期和Application生命周期一样,所以在NonStaticActivity关闭的时候,内部类实例依然持有对NonStaticActivity的引用,导致NonStaticActivity无法被回收释放,引发内存泄漏。

public class NonStaticActivity extends AppCompatActivity {
    private static Config sConfig;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_non_static);
        //Config类并不是静态类,
        sConfig = new Config();
    
    }
    
    class Config {
    
    }

}

 

3、匿名内部类导致内存泄露

比方说Thread、Handler等
1、new 出一个匿名的 Thread,进行耗时的操作,如果 MainActivity 被销毁而 Thread 中的耗时操作没有结束的话,便会产生内存泄露;
解决方法:继承 Thread  实现静态内部类
2、new 出一个匿名的 Handler,这时如果 MainActivity 被销毁,而 Handler 里面的消息还没发送完毕的话,Activity 的内存也不会被回收;
解决方法:
A:继承 Handler 实现静态内部类,以及在 Activity 的 onDestroy() 方法中,移除所有的消息 mHandler.removeCallbacksAndMessages(null);
 

ublic class MainActivity extends AppCompatActivity {
 
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            。。。。。。
        }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                。。。。。。
            }
        }).start();
 
 
        Message message = Message.obtain();
        mHandler.sendMessageDelayed(message, 10000);
    }

B:通过内部静态类和弱引用的方法来及时释放Activity,需要注意的是在Activity退出时记得清除掉消息队列中的消息


public class MainActivity extends AppCompatActivity {
    private MyHandler mHandler = new MyHandler(this);
    private TextView mTextView ;
    private static class MyHandler extends Handler {
        private WeakReference<Context> reference;
        public MyHandler(Context context) {
            reference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
}

4、单例造成的内存泄露

单例模式是非常常用的设计模式,使用单例模式的类,只会产生一个对象,这个对象看起来像是一直占用着内存,但这并不意味着就是浪费了内存,内存本来就是拿来装东西的,只要这个对象一直都被高效的利用就不能叫做泄露。

实质是静态变量引用Activity,在getInstance(Context context)方法中传入的参数context如果是某个Activity,但是Activity的生命周期较短,而单例作为Static对象是全生命周期的,这样当Activity结束后,单例对象仍然持有Activity的引用,GC机制无法判定为垃圾进行回收,此时发生内存泄露。

public class SingleInstanceTest {
 
    private static SingleInstanceTest sInstance;
    private Context mContext;
 
    private SingleInstanceTest(Context context){
        //不能直接使用Activity或者短周期的Context
        this.mContext = context.getApplicationContext();
    }
 
    public static SingleInstanceTest newInstance(Context context){
        if(sInstance == null){
            sInstance = new SingleInstanceTest(context);
        }
        return sInstance;
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!