您的位置:首页 > 移动开发 > Android开发

探究Android 关于Activity调用finish()方法后的内存释放情况

2016-07-24 22:22 537 查看
公司一直在做自己的硬件产品,但是运行内存只有512M,所有一旦后台的驻留应用过多,前台的应用就会很卡断。当然,原因有很多,我们产品的cpu有瓶颈,计算过慢,导致卡断。后台的常驻服务和应用过多,像QQ,微信,360,豌豆荚之类的。运行内存不足,内存管理机制就开始起作用,其中又涉及到swap分区等linux的相关知识…其实我们做应用层的,正常情况下,只需要关心自己的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,可能底层实现会不同的。

一点点的进步,总会有所成长的,与诸君共勉。晚安~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息