天天看点

Android如何安全退出多个Activity

      在做Android App的时候,几乎每个App都有一个“退出应用”的功能,如何做到完全退出一个App呢?Google了一些文章,都是都是通过List缓存Activity,在需要退出app的时候,迭代activity列表并调用finish方法,这种方案可以达到完全退出App的功能,但是潜在的问题很大,由于Activity被缓存导致不能被释放,容易导致OOM,因此这种方式需要慎用。

下面介绍一种解决方案,利用Activity启动时的flag属性来解决此问题,其性能优于通过缓存Activity来完全退出App的方案,只是这种解决方案需要满足一些条件(见分析过程)。

实现步骤:

1:创建一个“空”的辅助Activity,在其onCreate方法中调用finish方法。如下:

public class LastActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		finish();
	}
}
           

2:点击“退出App”的按钮执行以下方法:

findViewById(R.id.quit).setOnClickListener(new OnClickListener() {
	
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(SecondActivity.this,LastActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		SecondActivity.this.startActivity(intent);
		finish();
	}
});
           

通过这两个步骤可以实现退出整个应用。下面做一个简单地分析:

测试中使用三个Activity,其执行顺序为MainActivity -> SecondActivity -> LastActivity,在SecondActivity中,我们期望点击“退出app”按钮来实现完全退出App的功能,此时我们将借助一个辅助Activity(LastActivity)。

首先在触发点击事件后,在onClick方法中执行启动LastActivity操作。在执行点击事件前我们先查看任务栈中运行着的Activity,可以通过如下的命令查看:

adb shell dumpsys activity
           

其结果如下:

Android如何安全退出多个Activity

此时我们可以知道MainActivity跟SecondActivity属于同一个任务栈,且启动顺序为MainActivity -> SecondActivity。在onClick方法中我们准备启动LastActivity的时候,其Flag被设置为Intent.FLAG_ACTIVITY_CLEAR_TASK,该flag在android 文档中的表述为“If set in an Intent passed to 

Context.startActivity()

, this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started.”,其表达的意思为在启动新的Activity的时候,将清理跟此Activity“相关”的任务栈,此时除了栈中本身的Activity(SecondActivity)都将被清理,然后再启动Activity(LastActivity)。下面来验证其是否正确,在LastActivity的onCreate调用finish前加上断点,然后点击“退出App”按钮,查看任务栈的信息如下:

Android如何安全退出多个Activity

此时我们可以看出,在LastActivity被启动后,MainActivity被清理了,此时任务栈中只剩下LastActivity跟SecondActivity。接着运行LastActivity的finish方法,LastActivity退出,然后SecondActivty也退出,此时就退出App了。

上面的方式是所有的Activity都存在同一个任务栈中的情况,对于拥有不同任务栈的不同Activity是否也能真正意义上的完全退出App呢?下面我们将在AndroidManifest.xml文件中对SecondActivity跟LastActivity中做如下设置,使其位于不同的任务栈中:

<activity
      android:name=".SecondActivity"
      android:launchMode="singleTask"
      android:taskAffinity="com.umeng.social"
     />
<activity 
      android:name=".LastActivity"
      android:launchMode="singleTask"
      android:taskAffinity="com.umeng.social.test" 
     />
           

此时我们查看任务栈的情况,如下:

Android如何安全退出多个Activity

此时我们可以看见MainActivity跟SecondActivity在不同的任务栈中,此时点击退出App按钮后,其Activity栈的情况如下:

Android如何安全退出多个Activity

可以看到此时三个Activity都在不同的任务栈中。细心的同学可能已经发现问题了,为什么LastActivity已经启动,而MainActivity还没有被销毁?是的,这里就是上面提到的'清理跟此Activity“相关”的任务栈'中“相关”两字的特殊意义了,这说明在清理Activity时是有条件的,其条件为“被clean的Activity必须跟需要启动的Activity在同一任务栈中”。由于现在MainActivity、SecondActivity、LastActivity在不同任务栈中,因此Activity不会被清理。执行断点后续代码,此时Activity栈中依然存在MainActivity,导致整个App是不能完全退出的。

因此采用设置falg的方式完全退出App是有条件的,条件为:”整个App的Activity存在同一个任务栈中“或者任务栈模型满足以下条件:

Android如何安全退出多个Activity

目前对于拥有多个任务栈的情况完全退出App的情况暂时没有想到比较完美的解决方案,如果有小伙伴知道,请记得留言,谢谢。