Android Activity启动模式

来源:互联网 发布:普通笔记本装mac系统 编辑:程序博客网 时间:2024/06/16 16:11

Activity是Android里展示用户界面的重要组件,大部分的用户交互都需要通过它来实现。界面之间的跳转切换是应用交互的重要组成部分,所以很有必要对Activity的启动模式深入理解。Android系统使用栈BackStack来管理打开的Activity,通常情况下新打开的界面展示在最前面,也就是放在栈顶位置;但是有些界面比如主界面通常希望只展示一个,不希望产生多个实例,就需要系统提供相应支持。根据Activity和BackStack的管理方式系统提供了四种启动模式:
Standard标准启动模式:系统会直接创建新的Activity实例,然后把Activity压入BackStack。
SingleTop启动模式:系统首先检查栈里是否有该Activity的实例并且在栈顶,如果是就不创建新的实例,只调用已存在实例的onNewIntent方法;如果不存在就和标准启动模式一样。
这里通过写一个简单的测试程序来验证一下,创建一个包含四种启动方式的Activity:

public class StartModeActivity extends AppCompatActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setTitle("启动模式测试");        setContentView(R.layout.start_mode_activity);        Log.d("AndroidTest", "Task id = " + getTaskId());    }    public void singleTop(View v) {        Intent intent = new Intent(this, SingleTopActivity.class);        startActivity(intent);    }    public void singleTask(View v) {        Intent intent = new Intent(this, SingleTaskActivity.class);        startActivity(intent);    }    public void singleInstance(View v) {        Intent intent = new Intent(this, SingleInstanceActivity.class);        startActivity(intent);    }    public void standard(View v) {        Intent intent = new Intent(this, StandardActivity.class);        startActivity(intent);    }}

每个被启动的Activity也同样包含可以用四种启动方式的Activity,实验一下第一种启动模式,不停的点击标准启动按钮。在命令行窗口下输入adb shell dumpsys activity,里面展示了很多信息,只关注Running activities (most recent first)这个部分的内容,可以看到标准启动模式下一直在往backstack里push新的activity实例。图里的TaskRecord就是BackStack的类名,每个Activity对应一个ActivityRecord对象。
标准启动模式
然后来测试一下SingleTop启动模式,首先启动一个标准启动再启动一个SingleTop启动。栈里没有SingleTop实例,系统创建了一个新的实例。
SingleTop栈里没有实例
然后再启动一个SingleTop启动,栈里的Activity实例并没有改变,与上图一致。然后再启动一个标准启动,再启动一个SingleTop。可以看到虽然栈里已经有了SingleTop实例,可惜它并不在栈顶,系统就生成了一个新的实例并把它放到了栈顶。
SingleTop栈里有实例但不在栈顶
SingleTask启动模式:这种启动模式下在一个Task(也就是一个Backstack)里只会有一个对应Activity实例,如果Task里没有对应实例就新建一个入栈;如果Task里有并且在栈顶就只会调用这个栈顶的Activity的onNewIntent方法,如果不在栈顶会首先清空启动Activity之上的Activity然后调用对应Activity的onNewIntent方法。下面的图对应的是栈里没有SingleTask对应的情况,系统会新建一个实例然后入栈。之后标准启动一个实例,标准实例就会放到SingleTask的上方。
这里写图片描述
下面再启动一个SingleTask实例,看一下之后的任务栈Activity。这时因为栈里已经有了SingleTask实例,可以看到SingleTask上面的标准启动Activity被清除,并且SingleTask处于栈顶位置。再直接启动SingleTask的Activity,栈里的内容与下图一致,没有改变。
这里写图片描述
SingleInstance启动模式:该启动模式会新建一个全新的任务栈,然后把Activity放在栈底。直接启动一个SingleInstance的实例,查看栈内容。
SingleInstance启动模式
可以看到新建了一个新的task,再启动一个新的标准启动,查看任务栈内容。
从SingleInstance启动Activity
出现了一个任务栈但是这个任务栈编号是9094,跟MainActivity的栈是同一个栈,退出这个标准启动Activity之后查看栈内容。
这里写图片描述
可见SingleInstance的栈被移到了当前栈的后方。只有当MainActivity被弹出才会重新展示SingleInstance的界面。现在重新进入测试程序,启动一个SingleInstance实例,在SingleInstance里重新启动标准启动Activity,再重新启动一个SingleInstance,查看栈内容。可以看到系统重新将已经启动的SingleInstance实例放到了前台,并没有生成新的SingleInstance实例。
这里写图片描述

Activity的taskAffinity属性与启动后所在的任务栈有着密切的关系,Affinity单词是依附的意思,每个启动的Activity默认情况下依附在以应用的包名命名的task上,从前面的图片可以看到测试启动的Activity的任务栈都被命名为sankuai.com.androidlearn。为了测试这个属性,现在把几种启动模式的Activity都加上taskAffinity属性,查看任务栈内容。

<activity android:name=".StandardActivity"          android:taskAffinity="standard.task"          android:launchMode="standard"></activity><activity android:name=".SingleTopActivity"          android:taskAffinity="single.top.task"          android:launchMode="singleTop"></activity><activity android:name=".SingleInstanceActivity"          android:taskAffinity="single.instance.task"          android:launchMode="singleInstance"></activity><activity android:name=".SingleTaskActivity"          android:taskAffinity="single.task.task"          android:launchMode="singleTask"></activity>

启动顺序标准启动->SingleTop启动->SingleTask启动->SingleInstance启动,结果如下:
taskAffinity属性
启动顺序SingleInstance启动->SingleTask启动->SingleTop启动->标准启动,结果如下:
这里写图片描述
启动顺序SingleInstance启动->标准启动->SingleTop启动->SingleTask启动,结果如下:
这里写图片描述
启动顺序SingleInstance启动->SingleTop启动->标准启动->SingleTask启动,结果如下:
这里写图片描述
可以看到SingleTask和SingleInstance都在新的任务栈里启动,而标准启动和SingleTop启动会在启动它们的Activity的栈里启动(SingleInstance例外);在SingleInstance里启动的时候标准和SingleTop启动会在新的栈里启动,SingleTop和标准启动始终在同一个栈里。
现在开始讨论另外一个属性allowTaskReparenting,这个属性允许新启动的Activity进入后台后,用户启动和它taskAffinity相同的应用时最先展示该Activity。通过前面的分析可知标准启动和SingleTop启动(除SingleInstance之外)会始终在启动它们的任务栈里,所以测试的ReparentActivity即使配置了不同于MainActivity的taskAffinity依然与之处于相同任务栈里。现在添加一个ReparentActivity它的配置如下。

<activity android:name=".ReparentActivity"          android:taskAffinity="example.com.reparent"          android:allowTaskReparenting="true"></activity>

启动ReparentActivity,查看任务栈内容。
这里写图片描述
新建一个Reparent测试程序,然后启动它,再次查看任务栈内容。
这里写图片描述
可以看到新启动的应用最先展示的是ReparentActivity。

0 0
原创粉丝点击