1、基本概念
- Activit是与用户上层交互的入口点。
- 它表示拥有界面的单个屏幕。可以理解成一个绘制用户界面的窗口, 而这个窗口可以填满整个屏幕(也可能比屏幕小或者浮动在其他窗口的上方),在该区域内允许用户在上面做交互性操作。
- 一个App允许有多个Activity。比如管理系统,有登录的Activity,文件列表展示的Activity,编辑文章的Activity,查看文章的Activity。他们共同组成了一个完整的用户体验。但是各个Activity又相互独立。
2、Activity的生命周期:
3、Activity栈
- 我们的APP一般都是由多个Activity构成的,而在Android中给我们提供了一个Task(任务)的概念, 就是将多个相关的Activity收集起来进行管理。
- Application启动时,系统会为Application创建一个任务栈(Task)。
- 遵循【后进先出】的原则,当一个Activity启动另一个Activity的时候,第二个Activity压入第一个Activity栈中。此时两个Activity同时放在同一个Task中。
- 在栈顶的Activity就是设备当前显示的Activity。
- 我们对Activity的打开和关闭操作,就是将Activity压入(push)任务栈和从任务栈中弹出(pop)的操作。
举例:应用程序中存在A1,A2,A3三个activity,当用户在Launcher或Home Screen点击应用程序图标时, 启动主A1,接着A1开启A2,A2开启A3,这时栈中有三个Activity,并且这三个Activity默认在 同一个任务(Task)中,当用户按返回时,弹出A3,栈中只剩A1和A2,再按返回键, 弹出A2,栈中只剩A1,再继续按返回键,弹出A1,任务被移除,即程序退出!
Task是Activity的集合,是一个概念,是来存储和管理Activity的。当然可以有多个Task,但是 同一时刻只有一个栈在最前面,其他的都在后台!
Task是一个整体单元,当用户开始一个新任务或通过主屏幕按钮进入主屏幕时,任务可移至“后台”。在后台时,任务中的所有 Activity 都会停止,但任务的返回堆栈会保持不变,当其他任务启动时,当前任务只是失去了焦点
举例:我们通过点击通信录APP的图标打开APP,这个时候会新建一个栈1,然后开始把新产生的Activity添加进来,可能我们在通讯录的APP中打开了短信APP的页面,但是此时不会新建一个栈,而是继续添加到栈1中,这是 Android推崇一种用户体验方式,即不同应用程序之间的切换能使用户感觉就像是同一个应用程序, 很连贯的用户体验,官方称其为seamless (无缝衔接)!
这个时候假如我们点击Home键,回到主屏幕,此时栈1进入后台,我们可能有下述两种操作:
- 1)点击菜单键(正方形那个按钮),点击打开刚刚的程序,然后栈1又回到前台了! 又或者我们点击主屏幕上通信录的图标,打开APP,此时也不会创建新的栈,栈1回到前台!
- 2)如果此时我们点击另一个图标打开一个新的APP,那么此时则会创建一个新的栈2,栈2就会到前台, 而栈1继续呆在后台;
- 后面也是这样...以此类推!
注意:多个任务可以同时在后台进行。但是,如果用户同时运行很多后台任务,系统可能会为了恢复内存而开始销毁后台 Activity,导致 Activity 状态丢失。
4、Activity的四种加载模式详解
"standard"(默认模式)
默认值。系统在启动该 Activity 的任务中创建 Activity 的新实例,并将 intent 传送给该实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例。
singleTop的使用
- 如果当前任务的顶部已存在 Activity 的实例,则系统会通过调用其onNewIntent()方法来将 intent 转送给该实例,而不是创建 Activity 的新实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例(但前提是返回堆栈顶部的 Activity 不是该 Activity 的现有实例)。
- 例如,假设任务的返回堆栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈为 A-B-C-D;D 位于顶部)。收到以 D 类型 Activity 为目标的 intent。如果 D 采用默认的 "standard" 启动模式,则会启动该类的新实例,并且堆栈将变为 A-B-C-D-D。但是,如果 D 的启动模式为 "singleTop",则 D 的现有实例会通过onNewIntent()接收 intent,因为它位于堆栈顶部,堆栈仍为 A-B-C-D。但是,如果收到以 B 类型 Activity 为目标的 intent,则会在堆栈中添加 B 的新实例,即使其启动模式为 "singleTop" 也是如此。
- 使用singleTop模式的Activity在栈顶时只会在Task中存在一个实例,所以可以在以下场景中使用:
- 要打开的Activity处于栈顶,点击通知栏打开栈顶的Activity
- Activity需要启动一个Service,最后Service对栈顶Activity进行操作
- 特定情况时,如进行数据刷新,自己跳转自己,走onNewIntent()刷新数据
- 等等......
总之,singleTop比较适用于ChildActivity(非主架构Activity)
singleTask的使用
系统会创建新任务,并实例化新任务的根 Activity。但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其onNewIntent()方法将 intent 转送到该现有实例,而不是创建新实例。Activity 一次只能有一个实例存在。
- 当Task中存在Activity实例,不会创建Activity,而是销毁Activity上面所有其他的Activity,以此来使将要跳转的Activity处于栈顶显示;如果不存在,则在栈顶创建一个Activity实例,所以假如有人问如何快速关闭100个Activity,只要给跳转的Activity设置singleTask即可
- Activity单独使用singleTask,并不会创建一个新的Task
- singleTask的Activity如果设置了独立的taskAffinity属性值,启动时就会在新的Task中,否则会在已有Task中。
所以基于以上特性,比较适合主架构Activity(例MainActivity)设置为singleTask,或者一些经常使用,但是关闭和跳转不规律的Activity。
"singleInstance"
与 "singleTask" 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。
再举个例子,Android 浏览器应用在<activity>元素中指定 singleTask 启动模式,由此声明网络浏览器 Activity 应始终在它自己的任务中打开。这意味着,如果您的应用发出打开 Android 浏览器的 intent,系统不会将其 Activity 置于您的应用所在的任务中,而是会为浏览器启动一个新任务,如果浏览器已经有任务在后台运行,则会将该任务转到前台来处理新 intent。
5、Activity的创建流程和数据传递
Activity间的数据传递:
多个Activity间的交互(后一个传回给前一个)