在做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
其结果如下:
此时我们可以知道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”按钮,查看任务栈的信息如下:
此时我们可以看出,在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"
- />
此时我们查看任务栈的情况,如下:
此时我们可以看见MainActivity跟SecondActivity在不同的任务栈中,此时点击退出App按钮后,其Activity栈的情况如下:
可以看到此时三个Activity都在不同的任务栈中。细心的同学可能已经发现问题了,为什么LastActivity已经启动,而MainActivity还没有被销毁?是的,这里就是上面提到的'清理跟此Activity“相关”的任务栈'中“相关”两字的特殊意义了,这说明在清理Activity时是有条件的,其条件为“被clean的Activity必须跟需要启动的Activity在同一任务栈中”。由于现在MainActivity、SecondActivity、LastActivity在不同任务栈中,因此Activity不会被清理。执行断点后续代码,此时Activity栈中依然存在MainActivity,导致整个App是不能完全退出的。
因此采用设置falg的方式完全退出App是有条件的,条件为:”整个App的Activity存在同一个任务栈中“或者任务栈模型满足以下条件:
目前对于拥有多个任务栈的情况完全退出App的情况暂时没有想到比较***的解决方案,如果有小伙伴知道,请记得留言,谢谢。