内存泄漏针对方案.md

#内存泄漏针对方案

原文链接https://mp.weixin.qq.com/s/_s88Xjti0YwO4rayKvF5Dg

##一、

###1 针对【静态变量】

在不使用静态变量时 如

sTest = null  至为空

###2 针对【Context】

用到Context 尽量使用 Application 的 Context 避免直接传递 Activity

###3 针对【Activity】

一定要使用Activity 使用弱引用、软引用

//弱引用
WeakReference<Activity> weakReference = new WeakReference<Activity>(this);
Activity activity = weakReference.get();

//软引用
SoftReference<Activity> softReference=new SoftReference<Activity>(this);
Activity activity1 = softReference.get();

##二、 非静态内部类(匿名类)内存泄漏

说明:非静态内部类 (匿名类)默认就持有外部类的引用,当非静态内部类(匿名类)对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露。

  • (1) Handler 的内存泄漏

      1.首先,非静态的Handler类会默认持有外部类的引用,包含Activity等。
      2.然后,还未处理完的消息(Message)中会持有Handler的引用。
      3.还未处理完的消息会处于消息队列中,即消息队列MessageQueue会持有Message的引用。
      4.消息队列MessageQueue位于Looper中,Looper的生命周期跟应用一致。
    
    
       因此,此时的引用关系链是Looper -> MessageQueue -> Message -   Handler -> Activity。
      所以,这时退出Activity的话,由于存在上述的引用关系,垃圾回收器将无法回收Activity,从而造成内存泄漏。
    
  • (2) 多线程引起的内存泄漏

    我们一般使用匿名类等来启动一个线程,如下:

      new Thread(new Runnable() {
          @Override
          public void run() {
    
          }
      }).start();
      
      同样,匿名Thread类里持有了外部类的引用。当Activity退出时,Thread有可能还在后台执行,这时就会发生了内存泄露。
    

解决方法:

静态内部类

静态内部类不持有外部类的引用,如下:

private static class MyThread extends Thread{
        //...  
    }

Activity退出时,结束线程
同样,这里也是让线程的生命周期跟Activity一致。
其他非静态内部类(匿名类),都可以按照这个套路来:一个是改成静态内部类,另外一个就是内部类的生命周期不要超过外部类。

##三 集合类内存泄漏

说明:集合类添加元素后,将会持有元素对象的引用,导致该元素对象不能被垃圾回收,从而发生内存泄漏。

举个例子:

    List<Object> objectList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        Object o = new Object();
        objectList.add(o);
        o = null;
    }

虽然o已经被置空了,但是集合里还是持有Object的引用

解决方法:

清空集合对象
如下:

objectList.clear();
objectList=null;

##四 未关闭资源对象内存泄漏

该关的全关

1 IO流 File流

InputStream.close();
OutputStream.close();

2 注销广播

unregisterReceiver(receiver);

3 回收Bitmap

Bitmap.recycle();
Bitmap = null;

4 销毁 webView

@Override
protected void onDestroy() {
if( mWebView!=null) {
    ViewParent parent = mWebView.getParent();
    if (parent != null) {
        ((ViewGroup) parent).removeView(mWebView);
    }

    mWebView.stopLoading();
    // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
    mWebView.getSettings().setJavaScriptEnabled(false);
    mWebView.clearHistory();
    mWebView.clearView();
    mWebView.removeAllViews();
    mWebView.destroy();

}
super.on Destroy();
}

5 停止动画

属性动画中有一类无限动画,如果Activity退出时不停止动画的话,
动画会一直执行下去。因为动画会持有View的引用,View又持有
Activity,最终Activity就不能给回收掉。只要我们在Activity退
出把动画停掉即可。

animation.cancel();


内存泄漏常用检测工具

###leakcanary

###leakcanary是square开源的一个库,能够自动检测发现内存泄露,其使用也很简单:

在build.gradle中添加依赖:

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'

  //可选项,如果使用了support包中的fragments
  debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1'
}

如果遇到下面这个问题:

Failed to resolve: com.squareup.leakcanary:leakcanary-android
根目录下的build.gradle添加mavenCentral()即可,如下:

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
}

###AS 自带工具 Memory Profiler

发布了26 篇原创文章 · 获赞 6 · 访问量 7811

猜你喜欢

转载自blog.csdn.net/weixin_37558974/article/details/82760287