Android内存泄漏总结和leakcanary使用

leakcannary  github地址:https://github.com/square/leakcanary

什么是内存泄漏?

Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。但是当对象不再被应用程序使用,仍然被生命周期长的对象引用,垃圾回收器无法回收。

哪些情况会造成内存泄漏?

  • 错误使用单例造成的内存泄漏
  • Handler造成的内存泄漏
  • 线程造成的内存泄漏
  • 非静态内部类创建静态实例造成的内存泄漏
  • 由WebView引起的内存泄漏
  • 资源未关闭造成的内存泄漏

LeakCanary检测内存泄漏:

LeakCanary是Square公司出的开源框架(Square出品,必属精品),是一个Android和Java的内存泄露傻瓜化并且可视化的内存泄露分析工具,当检测到某个activity有内存泄露,LeakCanary会弹出通知,定位到内存泄露的位置。使用它大大减少OOM的问题,提高App的质量。

  1. 在 build.gradle 中加入引用:
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
  1. 创建Application配置并使用Application:
import android.app.Application;
import android.content.Context;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;

public class MyApplication extends Application{
    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();

        refWatcher = LeakCanary.install(this);
    }

    public static RefWatcher getRefWatcher(Context context){
        MyApplication application = (MyApplication)context.getApplicationContext();
        return application.refWatcher;
    }
}
  1. 使用 RefWatcher 监控 Activity:
public class TestActivity extends AppCompatActivity {
    private TextView textView;

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

        RefWatcher refWatcher = MyApplication.getRefWatcher(this);
        refWatcher.watch(this);
    }
}

模拟单例模式造成内存泄漏情景:

public class SingletonManager {
    private Context mContext;
    private static SingletonManager instance;

    private SingletonManager(Context context){
        mContext = context;
    }

    public static synchronized SingletonManager getInstance(Context context){
        if(instance == null){
            instance = new SingletonManager(context);
        }
        return instance;
    }
}

稍微玩弄一下就内存泄露了:

 

giphy.gif

当传入Activity的this,给SingletonManager.getInstance(this),当这个 Context 所对应的 Activity 退出时,由于该 Context 的引用被单例对象所持有,其生命周期等于整个应用程序的生命周期,所以当前 Activity 退出时它的内存并不会被回收,这就造成泄漏了。

修复方法:改成SingletonManager.getInstance(getApplicationContext())就可以了。

模拟Handler造成的内存泄漏情景:

Handler的生命周期和Activity可能不一致:当Activity销毁时,Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 对象将被线程 MessageQueue 一直持有,导致handler始终无法被释放掉。

public class TestActivity extends AppCompatActivity {
    private Handler handler = new Handler();

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

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },10000);
        finish();
    }
}

修复方法:

  1. 使用静态内部类
  2. 使用弱引用WeakReference
    项目中使用Handler可以写一个统一的Handler使用。
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.lang.ref.WeakReference;

public class TestActivity extends AppCompatActivity {
    private Handler handler = new MyHandler(this);

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

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },10000);
        finish();
    }

    public static class MyHandler extends Handler{
        private WeakReference<TestActivity> mActivity;

        public MyHandler(TestActivity activity){
            mActivity = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            if (mActivity.get() == null) {
                return;
            }

            //接受到消息的处理
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值