Activity的管理——任务栈
任务栈
Android Task 是用来存放Activity实例的容器,Android系统可以通过Task可以有序的对每个Activity进行管理,决定与用户交互的Activity(也就是栈顶的Activity)
- Android Task是一个栈结构,只有压栈、出栈的操作,具有先进后出的特点
- 启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity,这里需要注意一个App可以不止拥有一个任务栈,一个任务栈可以存放来不同应用的Activity
- 任务栈所有的Activity被移除时才会被销毁,任务栈也可以移至后台并保留栈内所有的Activity及状态信息
-
前台栈与后台栈,正在与用户交互的Activity存在的任务栈即为前台栈,其他则为后台栈,假设每个App只有一个任务栈,当我们切换使用APP时可以看到多个任务栈在后台,正在使用的APP的栈则是前台栈,当发生跳转其他应用时,后台栈被移动至前台成为前台栈,此时的返回操作则由前台栈接手,注意依然是两个栈
前台栈切换.png
Activity的启动模式
正常情况下,当一个Activity启动了另一个Activity的时候,新启动的Activity就会置于任务栈的顶端,并处于活动状态,启动它的Activity压入,处于停止状态,当用户按下返回键或者调用finish()方法时,系统会移除顶部Activity,让后面的Activity恢复活动状态,而不正常情况下就是给Activity设置特殊的启动模式使得我们的Activity跳转有了自定义的管理
模式 | 说明 | 补充 |
---|---|---|
Standard/标准模式 | 可存在多个实例,跳转到该Activity时会重新实例化并路由Intent给它 | 默认进入启动它的任务栈中(在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中) |
SingleTop/栈顶唯一 | 可存在多个,只当跳转时该Activity存在栈顶时进行复用,其他情况下会进行重新实例化 | 比如在某些情况下跳转某个Activity的操作发生了多次,使用这中模式就可以避免创建多个该Activity;默认任务栈同standard模式 |
SingleTask/栈内唯一 | 不存在多个,该Activity存在单独的栈内,且不存在其他Activity,不存在时进行实例化并存放至单独的栈内 | 例如App的登录界面,在退出到登录界面时,使用该模式可以不用对其他登录后的Activity做出栈操作而是自动清空原来之上的所有Activity |
SingleInstance/栈内唯一 | 不存在多个,该Activity存在单独的栈内,且不存在其他Activity,不存在时进行实例化并存放至单独的栈内 | 新建栈来存放,例如拨号界面 |
Activity的配置启动
Activity的启动模式可以通过清单文件和使用Intent设置Activity Flags来配置。
- AndroidManifest配置
android:launchMode="standard/singleTop/singleTask/singleInstance"
- 设置 Activity Flags 配置
- 写法
Intent intent = new Intent(SActivity.this, STestActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
- Activity Flags
属性名 | 说明 | 补充 |
---|---|---|
FLAG_ACTIVITY_NEW_TASK | 使用一个新的Task来启动一个Activity,但启动的每个Activity都将在一个新的Task | 该Flag通常使用在从Service中启动Activity的场景,由于Service中并不存在Activity栈,所以使用该Flag来创建一个新的Activity栈,并创建新的Activity实例 |
FLAG_ACTIVITY_SINGLE_TOP | 使用singletop模式启动一个Activity | 与指定android:launchMode="singleTop" 效果相同。 |
FLAG_ACTIVITY_CLEAR_TOP | 使用SingleTask模式来启动一个Activity | ,与指定android:launchMode="singleTask" 效果相同。 |
FLAG_ACTIVITY_NO_HISTORY | Activity使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中。 | |
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | 具有这个标记的Activity将不会出现在历史Activity列表中 |
带返回的启动Activity方法——StartActivityForResult
开发当中Activity与Activity的数据交互是通过Intent来进行,但普通的startActivity是没办法拿到将要启动的页面的交互后的数据,例如进入拍照页面后获取拍到的相片,因此Android这里设计了StartActivityForResult这一方法满足这一需求
- 使用界面跳转
//REQUEST_CODE 为大于0小于65535(0xFFFF)的整数,
Intent intent = new Intent(this, XXXActivity.class);
startActivityForResult(intent,REQUEST_CODE);
- 使用界面的接收
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//requestCode 用于判断是否启动哪个Activity的返回结果
//resultCode 与Activity.RESULT_CANCELED、Activity.RESULT_OK判断是否取成功
//data 传递数据的载体
}
- 跳转界面的返回
Intent data = new Intent();
setResult(Activity.RESULT_OK, data);
finish();
补充说明
- 开发艺术与探索中提到使用非Activity类型的context(ApplicationContext)启动标准模式的Activity会报错,这是因为此时无法确认新建的Activity所存放的栈,可以为此Activity指定FLAG_NEW_ACTIVITY_TASK标记位来避免报错
- REQUEST_CODE的大小限制是源码中校验规则限制,一旦超出范围则会抛出异常
/**
* Checks whether the given request code is a valid code by masking it with 0xffff0000. Throws * an {@link IllegalArgumentException} if the code is not valid.
*/
static void checkForValidRequestCode(int requestCode) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
} }
网友评论