一、生命周期

1. 生命周期流程
onCreate
进行一些初始化工作
onStart
由不可见变为可见,但未在前台,无法交互
Activity已经显示出来,但我们还看不到
onResume
可见,前台,可交互
onPause
正在停止;
onPause必须先执行完,新的Activity才会启动。
- 如A启动B:A.onPause --> B.onCreate、B.onStart、B.onResume --> A.stop
- 所以避免在onPause中做耗时操作,容易造成卡顿
- 打开新的Activty为透明主题或dialog:只调用onPause,不会回调onStop
onStop
即将停止;
做一些重量级的回收工作,不能太耗时。
- 释放可能泄露内存的资源,因为onDestory不一定会调用。
onDestory
即将销毁
- finish或系统kill进程时,onDestory不确定会立即调用,也不确定一定会调用
- 非必须的情况下,减少在这里释放资源
2.其它情况生命周期
2.1 透明覆盖、半遮挡
如图分支1,当A启动的Activity为透明主题,或弹出Dialog时:
- A只是onResume和onPause之间切换
2.2 启动Activity
如图分支2
- A启动B:A.onPause --> B.onCreate、B.onStart、B.onResume --> A.stop
- B返回键到A: B.pause --> A.onRestart、A.onStart、A.resume --> B.stop、destory
2.3 异常关闭
如图分支3,常见场景为:
启动其它Activity、Home键返回、锁屏...
onCreate(Bundle savedInstanceState)
bundle != null时为异常关闭后,系统重新创建
onRestart、onStart
onRestoreInstanceState
该回调一定是被回收后重建时调用
onResume、onPause
onSaveInstanceState
- 系统觉得有可能被回收时调用(并不一定得被回收了才调用)
- 在onStop之前,和onPause没有既定时序关系
onStop、onDestory
2.3.1 onRestore和onSave不一定是成对出现的
- onSaveInstanceState系统觉得有可能会被回收就调用,此时onRestoreInstanceState不一定会被调用
- onCreate中bundle != null、onRestoreInstanceState被调用了,说明异常终止了,onSaveInstanceState就会被调用
2.3.2 资源相关配置改变
当横竖屏切换时,系统会先将当前Activity销毁,然后重建一个新的。为了避免这样销毁重建的过程,可以在AndroidMainfest.xml中对OrientationActivity对应的配置
configChanges="orientation|keyboardHidden|screenSize"
2.3.3 系统内存不足被杀死,优先级:
前台进程>可见进程>service进程>后台进程>空进程
二、启动模式
standard
- 默认启动模式,
- 最通常,谁启动就在谁所在的任务栈。
- ApplicationContext启动standard模式,报错
- standard模式进入启动它的Activity所在的栈
- ApplicationContext没有任务栈
- 指定FLAG_ACTIVITY_NEW_TASK标记位,创建新的任务栈,实际是以singTask模式启动
singleTop
- 栈顶复用模式,栈顶有就复用,不会重建。
通过onNewIntent方法接收参数,onCreate、onReusme等方法不会被调用,因为它没有发生改变。
singleTask
- 栈内复用模式,单例模式,栈内有该Activity实例,则多次启动不会重新创建。
通过onNewIntent传递参数,onCreate等不会被调用。 - singleTask自带clearTop效果,会将该Activity实例以上的Activity出栈。如,ADCB,启动D,则栈内情况为AD,CB会被出栈。
- 启动singleTask模式时的过程:
当启动A时,系统先查找有没有A想要的任务栈(和TaskAffinity有关):
如果没有,就创建新的任务栈,压入A;
如果有,再查看栈内有没有A的实例:没有就创建压入A;有A的实例就复用,如果不在栈顶,就清空A实例以上的Activity。 - 与TaskAffinity配合
singleInstance
- 加强的singleTask模式
- 全局单例模式,整个系统中是单例的
- 具有独占性,即它会独自占用一个任务
- 被他开启的任何activity都会运行在其他任务中?
allowTaskReparenting
允许activity重新指定Task
- App1-->App2, 此时App2中的C页面在App1栈中
- home
- 点击App2图标,C页面从App1栈转入到App2栈中
- (测试standard、singleTop有效,singTask无效)
清单文件-Activity中有详细说明和其它属性
android:allowTaskReparenting=["true" | "false"]
android:alwaysRetainTaskState=["true" | "false"]
android:clearTaskOnLaunch=["true" | "false"]
android:finishOnTaskLaunch=["true" | "false"]
android:noHistory=["true" | "false"]
android:taskAffinity="string"
TaskAffinity
任务相关性,标识了Activity所需要的任务栈的名字。
-
只有和singleTask配合使用才会有效
-
没有TaskAffinity:
- 自己或别的APP启动都在默认的包名栈中
- 被其它APP启动后,home,点击图标,直接进入该页面(此时存在:App2栈、App1栈)
-
有TaskAffinity:
- 自己或别的APP启动都在设置的包名栈中
- 被其它APP启动后,home,点击图标,进入APP2的主页面(此时存在:App2栈、设置的包名栈、App1栈)
-
任务栈:只能以出栈入栈的方式,不能排序。先入后出。
总结
- 非Activity类型的context,standard模式启动Activity时报错。
需加上FLAG_ACTIVITY_NEW_TASK,这时是以singTask模式启动。 - 如果复用,通过onNewIntent传递参数
可在该方法中setIntent,以便在其它方法中getIntent拿到Intent - standard、singTop:谁启动,在谁的栈里
| 模式 | 应用场景 |
|---|---|
| standard | 正常启动Activity |
| singleTop | 启动同类型的页面,例如通知内容显示页面、搜索页面 |
| singleTask | 作为程序入口 |
| singleInstance | 需要与程序分离开的页面,例如闹铃的响铃界面、支付界面 |
三、dumpsys
通过dumpsys命令查询系统服务的运行状态(对象的成员变量属性值)。查看activity,广播,服务,电池,CPU等信息。
adb shell dumpsys activity
adb shell dumpsys activity a 包名 查看指定包名下的Activity栈信息
查找 "Running activites"
四、FLAG标志
内容杂乱,不做研究,用到再查阅。
五、匹配规则
Intent和过滤器
Intent 与 IntentFilter 匹配规则——张拭心
- Intent启动:Activity、Service、BroadcastReceiver
filter过滤规则
- 可以有多个intent-filter,同时匹配到action、category、data才算完全匹配,匹配任意一组即成功。
- 每个filter可以有多个action、category、data。
action匹配规则
- Intent中没有action匹配失败
- Intent中的任意一个action能匹配任意一个filter中的action即可
即:Intent中的action存在且必须匹配filter中的其中一个action。(只要有一个匹配上,Intent中其它的action没有匹配上也行)
category匹配规则
- Intent中可以没有category(系统默认加上DEFAULT这个category)
- 如果有,都必须和filter中的category匹配上
- 注意和action的区别
- action:至少有一个能匹配filter中的
- category:可以没有,如果有,所有的category都必须和filter中的匹配上
即:可以没有,如果有需和filter中全部匹配上。
data匹配规则
intent 中的 data 至少可以匹配过滤器中的一个。
通过隐式启动一个组件之前,可以先判断一下是否有符合条件的组件。
PackageManager/Intent:resolveActivity()
<activity
android:name=".activity.launchmode.SingleTaskActivity"
android:alwaysRetainTaskState="true"
android:label="singleTask"
android:launchMode="singleTask"
android:taskAffinity="top.varmin.task2">
<intent-filter>
<action android:name="top.varmin.action.test"/>
<category android:name="top.varmin.category.test"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="myapp.mycompany.com"
android:scheme="myapp"/>
</intent-filter>
</activity>