- 首先,介绍一下设置Activity的启动模式的方法之一,在Androidmainfest.xml中的标签中配置
<activity android:name=".ThirdActivity"
android:configChanges="orientation|screenSize"
android:launchMode="standard/singleTop/singleTask/singleInstance">
</activity>
launchMode后面的启动方式四选一
- 第二,在控制台查看模拟器的堆栈情况
打开控制台,输入:
adb shell dumpsys activity
//键入回车即可看到控制台信息
如果出现:adb: command not found则是由于没有配置环境变量导致的。
打开AS新建三个Activity[MainActivity/SecondActivity/ThirdActivity]
【1】standard:标准模式
(1)将三个Activity的启动模式都更改为“standard”(其实这一步没必要修改,activity的默认启动模式就是standard,为了有仪式感就修改一下吧)
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:configChanges="orientation|screenSize"
android:launchMode="standard">
</activity>
<activity android:name=".ThirdActivity"
android:configChanges="orientation|screenSize"
android:launchMode="standard">
</activity>
(2)为每个Activity设置一个Button,以下是每个activity的逻辑部分
//MainActivity
Button btFirst = (Button) findViewById(R.id.bt_first);
btFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
//SecondActivity
Button btSecond = (Button) findViewById(R.id.bt_second);
btSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(SecondActivity.this,ThirdActivity.class));
}
});
逻辑很简单,打开模拟器并部署项目
然后点击第一个Activity中的按钮跳转到第二个Activity,然后再跳转到第三个Activity
以下用A,B,C分别代表MainActivity,SecondActivity,ThirdActivity
这样相当于系统创建了创建了三个Activity的实例并将它们入栈
理论上压栈情况应该为这样:
C |
---|
B |
A |
接下来打开控制台输入:adb shell dumpsys activity
在偏下方位置就可以看到如下信息:
观察控制台便可发现,情况和我们预期的一样。图片中的后台任务栈中的实例就是Android桌面
【2】singleTop:栈顶复用模式
-
将C的启动模式改为singleTop模式
-
启动顺序为:A—>B—>C—>C(C—>C表示C自己启动自己,就是在C中添加一个Button,监听事件写为自己启动自己)
btThird.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(ThirdActivity.this,ThirdActivity.class)); } });`
重新部署程序,返回控制台输入:adb shell dumpsys activity
可以观察到此时栈中的情况为:
Task195 | C |
---|---|
Task195 | B |
Task195 | A |
系统并没有再创建一个C的实例,而是直接使用栈顶的启动模式为singleTop的C
- 再将B的启动模式也设置为singleTop
- 启动顺序为:A—>B—>C—>B(将C中Button的逻辑改为跳转到B)
- 控制台:adb shell dumpsys activity
可以观察到此时栈中的情况为:
Task196 | B |
---|---|
Task196 | C |
Task196 | B |
Task196 | A |
意料之中的事情是不是,,,
A—>B | 虽然B为singleTop模式,栈顶不存在B,B入栈 |
---|---|
B—>C | 和上面一样,栈顶为B,而非C。B和C都是singleTop,C入栈 |
C—>B | 此时栈顶为C,而非B,创建B的新的实例,新B入栈 |
【3】singleTask:栈内复用模式
- 将A、B、C的启动模式分别修改为
A | standard |
---|---|
B | singleTask |
C | standard |
- 启动顺序为:A—>B—>C—>B(跳转逻辑和上一个一样,不用做修改)
- 控制台:adb shell dumpsys activity
此时栈中的情况为:
Task197 | B |
---|---|
Task197 | A |
出问题了,C不见了(黑人脸问号???)
A | 部署项目,A入栈 |
---|---|
A—>B | 此时栈内没有B,创建B的实例,B入栈 |
B—>C | C为标准模式,创建C的实例,C入栈 |
C—>B | 分析在下面表格 |
C到B的过程中:!!!B为栈内复用模式,B的实例已经在栈内,系统并不会创建新的实例,但此时B又需要回到栈顶,并且栈为“后进先出”,所以怎么办呢?只能是C出栈了。C出栈之后,栈内情况就为AB |
---|
【4】singleInstance:单实例模式
- 将A、B、C的启动模式修改为:
A | standard |
---|---|
B | singleInstance |
C | singleInstance |
- 启动模式:A—>B—>C
- 控制台:adb shell dumpsys activity
此时栈内情况为:
Task202 | C |
---|
Task201 | B |
---|
Task200 | A |
---|
分析:
A在系统的前台任务栈中;
A启动了singleInstance模式的B,系统为B新创建了一个栈Task201;
B又启动了singleInstance模式的C,系统又为C新创建了一个栈Task202
因此,它们三出了A在系统前台任务栈中,B和C都分别住在系统新创建的栈中。
- 将A、B、C的启动模式修改为
A | standard |
---|---|
B | singleInstance |
C | standard |
- 启动顺序:A—>B—>C
- 控制台(…)
此时的栈的情况又为:
Task198 | C |
---|---|
Task198 | A |
Task199 | B |
---|
A、C同位于系统前台任务栈,singleInstance启动模式的B在系统新创建的Task199栈中
终于深刻的理解了这四种启动模式了!呼~~~