
Activity生命周期
图片来源于网络

当Activity意外终止(屏幕反转)时Activity会重新创建,其生命周期为:
onPause -> onStop -> onSaveInstance -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
用户可在onSaveInstance中进行数据保存,在onCreate和onRestoreInstanceState中进行数据恢复
// 存储数据
其中onSaveInstanceState方法和onRestoreInstanceState方法只有在activity被异常终止才会调用:
除了屏幕反转导致的Activity重建外,还有由于内存不足导致activity被系统杀死,activity分为以下几种状态:
- 前台
- 可视
- 后台
其中后台activity最易被杀死。
对于屏幕翻转导致的activity重建,可通过configChanges属性进行配置,设定翻转不重建activity:
<activity
常见的configChanges属性还有:

Activity启动模式
<
启动模式有:
- standard
- singleTop
- singleTask
- singleInstance
standard
该启动模式为默认启动模式,每启动一个Activity,无论Activity栈中是否有该Activity实例,都会新建一个实例压入Activity栈。
singleTop
会检查Activity栈顶是否存在该Activity实例,若存在则不重新创建,否则重新创建,压入栈。
singleTask
检查整个Activity栈中是否存在该Activity实例,若存在则将其上面的所有Activity出栈以将该Activity移至栈顶,如:
当Aactivity(A所在栈T从栈顶都栈底有ABCD)启动Bactivity时,T栈中的Activity顺序为:BCD。
任务相关性:
- taskAffinity
被启动的Activity会压入到启动该Activity的Activity的所在栈中,栈的名称一般是该应用的包名,但可通过taskAffinity属性更改:
被启动的Activity设定了taskAffinity值时,当其被启动时则会创建一个名为taskAffinity属性值的栈并将该Activity压入该栈。
需要注意的是:
- 名称必须要有.,如:io.github.grooters.demo.firsrTask而不能firstTask,否则报错:
Installation did not succeed.The application could not be installed: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED Installation failed due to: 'null'
- 必须配合singleTask,只有配合singleTask才能实现:
在启动另一个Activity时判断当前栈和被启动activity的taskAffinity是否相同,若不相同则将找名称为taskAffinity属性值的栈,没有则创建,然后将该栈移到前台。
如果启动模式为standard,则会出现名称为taskAffinity属性值的栈无法来到前台导致启动了目标activity但不可见。
- allowTaskReparenting
除了指定栈名称外,还可以配合属性allowTaskReparenting使用:
当应用1的Aactivity启动应用2的Bactivity时,由于启动B的Activity位于应用1中,即其所在的栈名称为应用1的包名,所以Bactivity的栈理应为应用1的包名。但如果allowTaskReparenting设置为true,则会将Bactivity迁移到应用2的栈(若没有设置taskAffinity属性栈名称即为应用2的包名,若设置了则为taskAffinity属性值)中。
- 图片来源于网络 *

<
Activity的启动标记
常见的有:
- FLAG_ACTIVITY_NEW_TASK
等同于singleTask的启动模式,先判断当前栈和被启动activity的taskAffinity是否相同,若不相同则将找名称为taskAffinity属性值的栈,没有则创建,然后将该栈移到前台。
- FLAG_ACTIVITY_CLEAR_TOP
将被启动Activity实例前的所有Activity出栈,如果是singleTask则将该实例移至栈顶,否则新建实例放到栈顶。
- FLAG_ACTIVITY_SINGLE_TOP
等同与singleTop的启动模式。
可通过以下代码查看栈信息(只能获取前台Activity信息):
adb shell dumpsys activity > activityInfo.txt
隐式启动
通过隐式启动Activity需要在AndroidManefist的Activity的定义中设置intent-filter,其中匹配属性有:
- action
- category
- data
在设置了intent-filter后,想要找到该intent,则需要通过Java代码设置相应action,category,data的值。
action
可在intent-filter中定义多个action,若要找到该intent只需要匹配其中一个action即可
AndroidManefist.xml:
<intent-filter>
Java:
intent
category
无法单独通过该属性找到intent,至少需要一个action或data才能找到intent。
可在intent-filter中定义多个category,Java代码中不需要全部实现,但Java代码中添加了的category,需要在AndroidManefist被全部定义,否则报错
由于会在Java代码中默认添加android.intent.category.DEFAULT这个category,所以每次设置intent-filter都需添加上这个category。
<intent-filter>
Java:
intent
data
这是一个通过Uri来寻找intent的方式,Uri格式为:
scheme://host:port/path
例如:
http[scheme]://www.lilinlang.github.io[host]:8080[port]/path[path]
其中scheme常见的有:
- file
将其设置为scheme,Java代码通过Uri寻找该intent会报错:
java.lang.RuntimeException: Unable to start activity ComponentInfo: android.os.FileUriExposedException:file://... exposed beyond app through Intent.getData()
- http
- content
该属性寻找intent的规则和action类似,只需与xml中设定的任意一个data匹配都可以找到intent。
除此之外,还需要为Uri设置mineType,常见的mineType:

AndroidManefist.xml:
<intent-filter>
Java:
intent
判断是否成功找到intent
- 通过Intent的resolveActivity方法:
ComponentName
通过调用该方法若能成功找到该intent,则返回该Activity的ComponentName对象,否则返回null:
拿到ComponentName,可以直接设置启动activity:
Intent
- 通过PackageManager的resolveActivity方法
// 只匹配category为DEFAULT的Activity