Android onFinish()不会回收内存

正常情况下,只需要关心自己的app是否会内容泄露,当设备内存不足时,我们的数据是否显示正确,页面是否能正常打开,保证app不会carsh。

我们关闭一个页面会调用finish()方法,然后再onDestroy()方法里面做一些释放操作,但是我们怎么知道这个Activity里面的内容有没有被释放了。

adb 提供了一个命令 adb shell dumpsys meminfo 包名 -d

可以查看当前应用程序的一些相关信息,类似与ddms一样,只不过它用数据来统计出来了。

本次测试的demo是用锤子T1手机来测试的,不同的手机效果可能不同,现在我们来看一下测试的demo,代码很简单的:

// activity_main 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff0000"
    android:orientation="vertical" >

</LinearLayout>

// MainActivity java 文件
package com.zhou.ui;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;

import com.example.adbdumpsystest.R;

public class MainActivity extends Activity {

    private LinearLayout mLinearLayout;

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

        mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout);
        mLinearLayout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(),
                        BActivity.class);
                startActivity(intent);
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

}

 

就这样一个空的Activity,背景红色,点击打开BActivity,也就是一个带TextView的空Activity。

我们在命令行运行:

adb shell dumpsys meminfo com.example.adbdumpsystest -d

得到如下信息:

这里写图片描述

这里面有好多东西我也还没搞明白,也在探索阶段,如有相关简介,恳请留言讨论。

我们主要看Object这一栏:

Views有7个,Activities有一个,AppContexts有4个,ViewRootImpl有1个,现在就分析就这几个。

我们是一个空布局,就一个LinearLayout控件,就有7个Views了,AppContexts为什么有四个了,正常情况下Activity一个,Application一个,应该只有2个的,为什么会多出两个?这个问题我到现在还没有弄明白原因。

当我们从MainActivity跳转到BActivity的时候,在来观看一下情况:

这里写图片描述

Views:15,ViewRootImpl:2,AppContexts:5,Activities:2,Activity加1了,所有AppContexts也会加1,但为什么Views会变成15了?不是应该14吗?因为我们的BActivity的布局里面有个TextView控件,所有Views会加1。

// activity_b布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000ff"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#ffffff"
        android:gravity="center"
        android:text="TextView" />

</LinearLayout>

 

现在我们在BActivity调用finish()方法,回到上一个Activity,在来查看下内存,你会发现仍然还是上面的数据。这时候就疑问了,我们明明调用了finish()方法,Activity的onDestroy()方法也调用了,为什么还是会在这adb命令上显示呢?可能你会怀疑,是不是adb命令出问题了?其实不是的,我在网上查阅相关资料,他们说这是Android的一种机制,可以让下次打开app的速度快点,所有不会被回收掉。为力证明这个猜想,我们在ddms里面手动调用GC,回收内存,再来查看。

这里写图片描述

发现正常了,BActivity被回收掉了。我们极端一点,不停的打开关闭BActivity,然后来看下内存占用情况:

这里写图片描述

积攒了这么多了,那么来手动GC一下,然后你会发现,都会被正常回收掉,只留下一个当前正在显示的MainActivity,所以显示就是第一次打开MainActivity的内存占用情况。那么我们在看看如果MainActivity也被finish掉的情况是怎样的,记住要手动GC。

这里写图片描述

哇,原来一个界面都没有的话,也会有2个AppContexts,这到底是什么玩意?为什么啊?我也还在探索之中,等有了新的发现,也会更新相应内容的。

那么,我们可以得出结论,Activity调用finish()方法后,并不会被释放内存,只有内存不够时,触发GC回收,才会释放无用的内存。

那我们如果想要强制去释放它,那应该怎么做了,做了一个有趣的实验,如果你想要finish()一个界面的时候,你可以试试调用System.exit(0)方法。它会强制去回收内存的,关于这个方法的用法和主要要点,晚上资料很多的。

最后在补充说一句,如果我们在Recent最近任务列表中,把最近运行的任务给清除掉,你在查看内存的话,你会发现得到下面的提示:

这里写图片描述

其实,你在最外层的Activity调用System.exit(0)方法,也会得到这样的提示,意味着你退出应用,就不再最近的运行列表中。所有最好不要再最外层的Activity调用System.exit(0)方法。

注意:我用小米的的手机测试过,finish()掉Activity过后,Activities的数量会减一的,相应的也会被释放的,所有针对不同的手机rom,可能底层实现会不同的。

posted @ 2017-02-20 16:03  猴子1  阅读(501)  评论(0编辑  收藏  举报