1. Activity 的生命周期有哪些?
- onCreate:在 Activity 初始化的时候会调用一次,可以在这个方法里面初始化布局和一些数据
- onStart:表示 Activity 已经可见了,但是还没有显示在前台,还无法和用户交互
- onResume:此时 Activity 已经处于前台,用户可见并可以进行交互
- onPause:表示 Activity 正在停止,可以在这个方法里面做一些不太耗时的释放工作
- onStop:表示 Activity 即将停止,可以做一些稍微重量级的回收操作,同样不能太耗时
- onDestory:表示 Activity 即将被销毁,可以做资源的最终释放
- onRestart:表示 Activity 正在重新启动,当 Activity 从不可见重新变为可见时,onRestart 就会被调用
2. 两个 Activity 跳转以及按 Home 键返回桌面的生命周期调用?
- A -> B:A onPause -> B onCreate -> onStart -> onResume -> A onStop
- B -> A:B onPause -> A onRestart -> onStart -> onResume -> B onStop -> onDestory
- Home:onPause -> onStop
- Home -> A:A onRestart -> onStart -> onResume
3. 横竖屏切换时的生命周期调用?
没有设置 Activity 的 android:configChanges
切屏会默认销毁当前 Activity,然后重新创建 Activity,会重走各个生命周期调用。
设置了 Activity 的 android:configChanges="orientation|screenSize"
切屏不会销毁和重新创建 Activity,只会执行 onConfigurationChanged 方法。
4. 如何保存 Activity 的状态?
在 onSaveInstanceState 方法中将数据保存在 Bundle 中,在 onCreate 方法或者 onRestoreInstanceState 方法中的 Bundle 参数取回数据。
5. 有哪些启动模式?onNewIntent 的调用时机?应用场景有哪些?
standard:
标准模式,也是系统的默认模式,每启动一个 Activity 都会创建一个新的实例压入栈顶,谁启动了这个 Activity,这个 Activity 就会运行在启动它的 Activity 所在的栈中。
这个模式下的 Activity 不会调用 onNewIntent 方法
singleTop:
栈顶复用模式,在这种模式下,如果新的 Activity 已经位于任务栈的栈顶,就不会创建新的实例,同时 onNewIntent 方法会被调用。
如果新 Activity 的实例存在于任务栈内,但是不在栈顶,那么就会创建新的 Activity 实例并压入栈顶。
应用场景:搜索界面、通知栏进入的界面
singleTask:
栈内复用模式,在这种模式下,在这种模式下,只要一个栈中存在此 Activity 的实例,那么多次启动此 Activity 都不会创建新的实例,只会调用其 onNewIntent 方法,同时,由于 singleTask 模式默认具有 clearTop效果,会导致栈内所有在此 Activity 之上的 Activity 全部出栈。
应用场景:应用主页
singleInstance:
单实例模式,这个模式具有 singleTask 所有的特性,还加强了一点,这个模式的 Activity 只能单独的位于一个任务栈中。
6. 在 Service 或者 Receiver 中,如何启动 Activity,原理是什么?
因为 standard 模式下的 Activity 会默认运行在启动它的 Activity 的任务栈中,但是非 Activity 的 Context 并没有所谓的任务栈,所以直接启动就会报错,需要为待启动的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 标志位,这样启动它的时候就会为它创建一个新的任务栈,相当于以 singleTask 模式启动了这个 Activity。
7. TaskAffinity 属性的作用是什么?
TaskAffinity 属性标识了一个 Activity 所需要的任务栈的名字。
默认情况下,所有 Activity 所需的任务栈的名字都为包名。
TaskAffinity 属性主要和 singleTask 启动模式或者 allowTaskReparenting 属性配对使用。
- 与 singleTask 启动模式时搭配时,待启动的 Activity 会运行在名字和 TaskAffinity 相同的任务栈中
- 与 allowTaskReparenting 属性搭配时,当一个应用 A 启动应用 B 的某个 Activity 后,如果这个 Activity 的 allowTaskReparenting 属性为 true,那么当应用 B 被启动后,此 Activity 会直接从应用 A 的任务栈转移到应用 B的任务栈中
8. 有几种方式给 Activity 指定启动模式,哪种方式优先级高?
有两种方式,第一种是在清单文件中指定,第二种是通过在 Intent 中设置标志位来指定。
第二种方式的优先级高于第一种。
第一种方式无法直接为 Activity 设定 FLAG_ACTIVITY_CLEAR_TOP 标识,第二种方式无法为 Activity 指定 singleInstance 模式 。
9. 启动 Activity 有哪些常用的 Flag?
- FLAG_ACTIVITY_NEW_TASK:为 Activity 指定 singleTask 启动模式
- FLAG_ACTIVITY_SINGLE_TOP:为 Activity 指定 singleTop 启动模式
- FLAG_ACTIVITY_CLEAR_TOP:启动具有此标志位的 Activity,在同一个任务栈中所有位于它之上的 Activity 都要出栈,这个标志位一般和 FLAG_ACTIVITY_NEW_TASK 搭配使用
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有这个标志位的 Activity 不会出现在历史 Activity 列表中,等同于在清单文件中指定 Activity 的属性 android:excludeFromRecents="true"
10. 两个 Activity 之间传递数据的方法?
- Intent
- BrocardReceiver
- ContentProvider
- 静态变量
- 外部存储,如 File,SharedPrefrences,数据库等
- EventBus、RxBus
11. 启动 Activity 的方式有哪些,优先级如何?
第一种显式调用,需要明确地指定被启动 Activity 的包名、类名等。
第二种隐式调用,需要 Intent 能匹配目标 Activity 的 IntentFilter 中设置的过滤规则,如果不匹配则无法启动目标 Activity。
显式调用的优先级高于隐式调用。
12. IntentFilter 的匹配规则有哪些?
- IntentFilter 的过滤信息有 action、category、data 三种
- 只有一个 Intent 同时匹配 action、category、data 三种类别信息才算完全匹配,只有完全匹配才能启动目标 Activity
- 一个 Activity 可以有多个 intent-filter,一个 Intetn 只要能匹配任何一组 intent-filter 就能启动目标 Activity
- action 的匹配规则要求 Intent 中的 action 存在且必须和过滤规则中的其中一个 action 相同,这里的相同指的是字符串值完全一样,另外,action 区分大小写
- category 的匹配规则要求 Intent 中如果含有 category,那么所有的 category 必须和过滤规则中的其中一个 category 相同
- Intent 可以不设置 category,系统在调用 startActivity 或 startActivityForResult 的时候会默认为 Intent 加上 android.intent.categoty.DEFAULT 这个 category
- 为了我们的 Activity 能够接收隐式调用,就必须在 intent-filter 中指定 android.intent.categoty.DEFAULT 这个 category
- data 的匹配规则要求如果过滤规则中定义了 data,那么 Intent 中必须含有可匹配的 data,这里的匹配指的是过滤规则中出现的 data 部分也出现在了 Intent 的 data 中
13. setResult 和 finish 的调用关系
问题:如果不能在 setResult() 之后立刻调用 finish() 方法,那么 setResult() 该在哪里调用?
Activity-A 通过 startActvityForResult() 打开了 Activity-B,B 退回 A 过程
B-onPause
A-onActivityResult
A-onRestart
A-onStart
A-onResume
B-onStop
B-onDestory
由源码可以看出,Activity 返回 result 是在 finish 的时候,也就是调用 setResult() 方法必须在 finish 之前,
又因为 A 的 onActivityResult() 需要在 B 的 onPause() 之后且 A 的 onRestart() 之前调用,而 onPause() 的调用不一定是在 finish() 之前,所以 B 中的 setResult() 方法要放在 B 的 onPause 之前调用。
解决方法:可以重写 onBackPressed() 方法,在执行默认的返回方法之前 setResult()
@Override
public void onBackPressed(){
setResult();
super.onBackPressed();
}
执行过程为
B-onBackPressed
B-finish
B-onPause
A-onActivityResult
A-onRestart
A-onStart
A-onResume
B-onStop
B-onDestroy
网友评论