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
其结果如下:
此时我们可以知道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" />