前言

  当前你已经入门Android开发,开始关注深入的问题,你就会碰到一个Android开发阶段经常碰到的问题,那就是内存泄漏. 其实大多数Android的内存泄漏都是因为activity里的资源释放不正确导致,activity与单例或者接口互相持有无法释放.这篇博客就来讲解如何在Android里最优的释放资源.

错误释放资源的一些例子

  在看正面例子之前,我们看看反面例子,了解为什么经常莫名其妙的内存泄露

在Activity的onDestroy()的生命周期里释放资源

在下面的onDestroy()方法里我们有一个叫mHttpList的资源要释放,我们都知道activity的生命周期的最后是onDestroy方法,那么为什么在onDestroy()里释放资源会有问题呢?

  问题出在onDestroy()生命周期并不是立即执行的.Activity退出前台后先是进入栈里的.是否执行onDestroy()是交给系统决定的,一般情况下系统的确会及时的运行onDestroy()方法销毁activity,但是在一些Activity跳转频繁的情况下可能系统并不会马上运行onDestroy()方法.这个时候问题就出现了你认为应该结束的资源并没有马上结束可能导致一些回调报错或者内存泄露.

  @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mHttpList != null){
            mHttpList.release();
            mHttpList = null;
        }

    }

在Activity的finish()方法里释放资源

同上环境,那么finish方法里释放资源有那些问题呢?

  重写的finish()是一个释放资源的好地方,在按返回键(或者你自己主动调用onBackPressed()方法)和主动调用finish()方法时,重写的finish()都是会运行的.但是在这个方法在有一种情况下是不运行的,就是在后台太久后的自动清理或者其他Activity的启动模式是android:launchMode="singleTask"  在其他activity的singleTask下会自动清理它栈前的所以Activity,在这种情况下如果你的activity要被清理掉finish()方法是不会运行的.这样你的资源就没有被释放了.

    @Override
    public void finish() {
        super.finish();
        if (mHttpList != null){
            mHttpList.release();
            mHttpList = null;
        }
    }

在Activity的onPause()和onStop()里释放资源

onPause()和onStop()我们都知道activity后台的时候会调用这2个生命周期先onPause() 然后在 onStop(),如果是Dialog模式的Activity弹出只会进入onPause(). 他们的问题是什么呢?

  问题是如果在操作太快的操作前后台,就会导致我们的资源需要频繁的在onRestart()或者onResume() 重新初始化或者注册.这是较好的一种释放资源的方式一般情况下是推荐这种的,但是快速频繁的操作初始化与释放是最容易出现内存泄漏的...特别是初始化如果是耗时的...

@Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG, "onStop: ");
    }

推荐在Activity里释放资源的方式

   onPause()或者onStop()结合onDestroy(),调用isFinishing()在方法判断后释放资源,如下代码:    

  private void release(){ //释放资源的方法
        if (isFinishing()) {
            if (mHttpList != null) {
                mHttpList.release();
                mHttpList = null;

            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        release();//释放资源

    }

    @Override
    protected void onStop() {
        super.onStop();
        //结合实际情况也可以在onStop方法里 释放资源

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        release();//释放资源
    }

  注意添加判空,来防止重复释放...  这里为什么onDestroy()还要运行一次下面说明

  isFinishing()的作用就是判断这个activity是不是需要被销毁,还是只是进入后台.我验证过以下情况:

1.在主动调用finish()方法的情况下,isFinishing() 返回的是true

2.在主动调用onBackPressed()方法或者按返回键的情况下, isFinishing() 返回的是true

3.如果只是因为进入到其他Activity而退到后台, isFinishing() 返回的是false

但是,这并不是完美的还有一种情况可以跳过清理的,那就是SingleTask模式下这个Activity要被销毁

12-18 13:14