AndroidAndroid 优化方案Android性能优化

Android 优化一: Leakcanary检测内存泄漏汇总

2017-08-16  本文已影响309人  杨充211

Leakcanary检测内存泄漏汇总
目录介绍:
1.什么是内存泄漏
2.内存泄漏造成什么影响
3.内存泄漏检测的工具有哪些
4.关于Leakcanary使用介绍
5.Leakcanary捕捉常见的内存泄漏及解决办法
5.1 错误使用单例造成的内存泄漏
5.2 错误使用静态变量,导致引用后无法销毁【工具类使用不当导致内存泄漏】
5.3 Handler造成的内存泄漏
5.4 线程造成的内存泄漏
5.5 由WebView引起的内存泄漏
5.6 资源未关闭造成的内存泄漏
5.7 未注销EventBus导致的内存泄漏
5.8 静态集合使用不当导致的内存泄漏
5.9 使用弱引用避免内存泄漏
6.其他

1.什么是内存泄漏?
一些对象有着有限的声明周期,当这些对象所要做的事情完成了,我们希望它们会被垃圾回收器回收掉。但是如果有一系列对这个对象的引用存在,那么在我们期待这个对象生命周期结束时被垃圾回收器回收的时候,它是不会被回收的。它还会占用内存,这就造成了内存泄露。持续累加,内存很快被耗尽。
比如:当Activity的onDestroy()方法被调用后,Activity以及它涉及到的View和相关的Bitmap都应该被回收掉。但是,如果有一个后台线程持有这个Activity的引用,那么该Activity所占用的内存就不能被回收,这最终将会导致内存耗尽引发OOM而让应用crash掉。

2.内存泄漏会造成什么影响?
它是造成应用程序OOM的主要原因之一。由于android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。

3.内存泄漏检测的工具有哪些
最常见的是:Leakcanary

4.关于Leakcanary使用介绍
leakCanary是Square开源框架,是一个Android和Java的内存泄露检测库,如果检测到某个 activity 有内存泄露,LeakCanary 就是自动地显示一个通知,所以可以把它理解为傻瓜式的内存泄露检测工具。通过它可以大幅度减少开发中遇到的oom问题,大大提高APP的质量。
关于如何配置,这个就不说呢,网上有步骤

5.Leakcanary捕捉常见的内存泄漏及解决办法

public class LoginManager {
    private static LoginManager mInstance;
    private Context mContext;

    private LoginManager(Context context) {
        this.mContext = context;          //修改代码:**this.mContext = context.getApplicationContext();**
    }

    public static LoginManager getInstance(Context context) {
        if (mInstance == null) {
            synchronized (LoginManager.class) {
                if (mInstance == null) {
                    mInstance = new LoginManager(context);
                }
            }
        }
        return mInstance;
    }

    public void dealData() {}
}
LoginManager.getInstance(this).dealData();
Image.png
要保证Context和AppLication的生命周期一样,修改后代码如下:
this.mContext = context.getApplicationContext();
DoShareUtil.showFullScreenShareView(PNewsContentActivity.this, title, title, shareurl, logo);
**非静态内部类,静态实例化**
public class MyActivity extends AppCompatActivity {
    //静态成员变量
    public static InnerClass innerClass = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        innerClass = new InnerClass();
    }

    class InnerClass {
        public void doSomeThing() {}
    }
}

这里内部类InnerClass隐式的持有外部类MyActivity的引用,而在MyActivity的onCreate方法中调用了。
这样innerClass就会在MyActivity创建的时候是有了他的引用,而innerClass是静态类型的不会被垃圾回收,
MyActivity在执行onDestory方法的时候由于被innerClass持有了引用而无法被回收,所以这样MyActivity就总是被innerClass持有而无法回收造成内存泄露。
public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler();
    private TextView mTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text);        //模拟内存泄露
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mTextView.setText("yangchong");
            }
        }, 2000);
    }
}
@Override
protected void onDestroy() {
    super.onDestroy();
    if(handler!=null){
        handler.removeCallbacksAndMessages(null);
        handler = null;
    }
}
public class MainActivity extends AppCompatActivity {

    private AsyncTask<Void, Void, Integer> asyncTask;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text);
        testAsyncTask();
        finish();
    }

    private void testAsyncTask() {
        asyncTask = new AsyncTask<Void, Void, Integer>() {
            @Override
            protected Integer doInBackground(Void... params) {
                int i = 0;
                //模拟耗时操作
                while (!isCancelled()) {
                    i++;
                    if (i > 1000000000) {
                        break;
                    }
                    Log.e("LeakCanary", "asyncTask---->" + i);
                }
                return i;
            }

            @Override
            protected void onPostExecute(Integer integer) {
                super.onPostExecute(integer);
                mTextView.setText(String.valueOf(integer));
            }
        };
        asyncTask.execute();
    }
}
private void destroyAsyncTask() {
    if (asyncTask != null && !asyncTask.isCancelled()) {
        asyncTask.cancel(true);
    }
    asyncTask = null;
}

@Override
protected void onDestroy() {
    super.onDestroy();
    destroyAsyncTask();
}
public class MainActivity5 extends AppCompatActivity {
    private WebView mWebView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);
        mWebView = (WebView) findViewById(R.id.web);
        mWebView.loadUrl("http://www.cnblogs.com/whoislcj/p/5720202.html");
    }
}
@Override
protected void onDestroy() {
    if (mWebView != null) {
        mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        mWebView.clearHistory();
        ViewGroup parent = (ViewGroup) mWebView.getParent();
        if(parent!=null){
            parent.removeView(mWebView);
        }
        mWebView.destroy();
        mWebView = null;
    }
    super.onDestroy();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_common);
    EventBus.getDefault().register(this);
}

@Subscribe
public void onEvent(MessageEvent msg) {

}

@Override
protected void onDestroy() {
    super.onDestroy();
    //未移除注册的EventBus
    //EventBus.getDefault().unregister(this);
}
public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<Activity>();
    public static void addActivity(Activity activity) {
        activities.add(activity);
    }
    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_common);
    ActivityCollector.addActivity(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    //静态集合没有移除元素
    //ActivityCollector.removeActivity(this);
}
public class WeakReferenceActivity extends AppCompatActivity {

    //将Handler声明为静态 没有了Activity的引用, 无法直接引用其变量或方法,
    //使用弱引用WeakReference来解决这个问题
    private static class DBHandler extends Handler {
        //弱引用, 而不是使用外部类this或者传进来
        private final WeakReference<WeakReferenceActivity> mActivity;
        public DBHandler(WeakReferenceActivity activity) {
            mActivity = new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            WeakReferenceActivity activity = mActivity.get();
            if (activity != null) {
                Toast.makeText(activity, "what: " + msg.what, Toast.LENGTH_SHORT).show();
            }
        }
    }

    private final DBHandler mHandler = new DBHandler(this);

    private static final Runnable sRunnable = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(App.getInstance(), "sRunnable run()", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weak_reference);
        mHandler.postDelayed(sRunnable, 1000 * 20);
    }

    public void onClick(View view) {
        mHandler.sendEmptyMessage(new Random().nextInt(10));
    }
}

后续:
平时喜欢写写文章,笔记。别人建议我把笔记,以前写的东西整理,然后写成博客,所以我会陆续整理文章,只发自己写的东西,敬请期待。如果有什么问题或者需要笔记,可以直接联系我,可以发送印象笔记文档给你!
知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
领英:https://www.linkedin.com/in/chong-yang-049216146/
简书:http://www.jianshu.com/u/b7b2c6ed9284
csdn:http://my.csdn.net/m0_37700275
网易博客:http://yangchong211.blog.163.com/
新浪博客:http://blog.sina.com.cn/786041010yc
github:https://github.com/yangchong211
喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
脉脉:yc930211
开源中国:https://my.oschina.net/zbj1618/blog
邮箱:yangchong211@163.com

上一篇 下一篇

猜你喜欢

热点阅读