Android 几种关于内存泄漏情况和优化

内存泄漏

  • LeakCanary,Square公司开源的第三方内存检测工具
  • 内存泄露VS内存溢出
    内存溢出:超出了虚拟机分配的内存
    内存泄露:某个不再使用的对象被其他实例引用,导致其不能被回收,内存泄露有可能引起内存溢出

内存泄漏原理

  • 长生命周期对象,持有了短生命周期对象的引用,导致了短生命周期对象无法被回收

1.单例引起的内存泄漏

public class SingleInstance {
    private Context context;
    private static SingleInstance instance;

    private SingleInstance(Context context) {
        this.context = context;
    }

    public static SingleInstance getInstance(Context context) {
        if (instance == null) {
            instance = new SingleInstance(context);
        }
        return instance;
    }
}
        /**
         * 创建一个单例的时候,会传入一个context
         */
        /**
         * 如果传入的context是activity的话
         * 在activity退出的时候,单例对象持有了activity的引用,导致activity不能被回收
         * 长生命周期对象,持有了短生命周期对象的引用,导致短生命周期对象在想要被回收的时候无法被回收。
         */
        SingleInstance instance1 = SingleInstance.getInstance(MainActivity.this);
        /**
         * 传入getApplicationContext()可以解决这个问题
         * Application的生命周期就代表了整个应用的生命周期,
         * 单例的静态属性导致了单例的生命周期也是整个应用
         */
        SingleInstance instance2 = SingleInstance.getInstance(getApplicationContext());

2.Handler引起的内存泄漏

import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;


public class Main2Activity extends AppCompatActivity {
    /**
     * 非静态内部类,Handler会持有外部类的引用,
     */
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Message message = new Message();
        message.what = 1;
        /**
         * 消息延时10分钟发送
         * 同时message持有了handler的引用
         * 而handler是非静态内部类持有了Activity的引用,导致GC无法回收activity
         */
        handler.sendMessageDelayed(message, 60 * 10 * 1000);
    }
}
  • 解决Handler的内存泄露
    1.避免使用handler的非静态内部类
    2.通过弱引用来引用activity
    3.使用静态引用
    4.销毁的时候,移除掉Message
public class NoLeakActivity extends Activity {
	//3.使用静态引用
    private static NoLeakHandler handler;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		
        handler = new NoLeakHandler(NoLeakActivity.this);

        Message message = Message.obtain();
        message.what = 1;
        handler.sendMessageDelayed(message, 10 * 60 * 1000);
    }

	//4.activity销毁时,移除所有message
    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }

	//1.使用静态内部类
    private static class NoLeakHandler extends Handler {
    	//2.在需要传入Activity引用的时候使用弱引用
        private WeakReference<NoLeakActivity> mActivity;

        public NoLeakHandler(NoLeakActivity activity) {
            this.mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                
            }
        }
    }
}

3.线程引起的内存泄漏

  • AsyncTask,Runnable,Thread
    如果以匿名内部类的形式创建的话,他们就会持有当前Activity的隐式的引用,如果Activity在被销毁之前,AsyncTask,Thread中的耗时任务没有执行完,导致Activity不能被回收。

  • 解决办法和Handler类似:
    1.使用静态内部类的方式,避免内存泄露
    2.在Activity被销毁的时候,取消掉AsyncTask中的任务

4.WebView引起的内存泄漏

  • 打开新页面的时候,为了能够快速回退,之前页面占用的内存也不会被释放掉,加载网页较多的时候,将会导致系统不堪重负。在onDestroy中销毁webview也是无效的。

  • 解决方法:
    将webView放在一个单独的进程中。

其他内存优化的方法:

  • 1.当service完成后,尽量停止他。(推荐IntentService)
    可以用IntentService来代替Service。IntentService继承自Service,Service在主线程,不能进行耗时操作。IntentService内部会开启一个子线程来执行耗时操作。IntentService完成后会自动退出,而Service需要手动调用stopService来退出。如果开发人员忘记了关闭Service将会造成内存的泄露。

  • 2.使用多进程。
    定位服务,webview,push等,开启单独的进程。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值