Android 笔记:Activity 二三事

2018-03-05  本文已影响11人  tianma

原文地址: http://tianma.space/post/579806496/

本文主要记录一些与 Activity 相关的,并不是很容易弄清楚的点。

Activity 生命周期

先上 Google 官方的图:


Activity 生命周期

这里又引申出 Activity 相关的三个生存期:

异常情况下的生命周期

Activity 异常情况重建过程

这里的 异常情况 主要指以下两种情况:

  1. 系统相关的资源配置发生改变产生的异常:
    如果Activity不作特殊处理,当系统配置发生改变(比如屏幕方向发生改变),Activity就会被销毁并重建,onSaveInstanceState()onRestoreInstanceState() 这两个方法就会在这一过程中被调用。

  2. 内存资源不足导致 Activity 被回收的异常:
    Activity会有优先级分级情况,优先级依次降低:

    • 前台 Acitivty,即正在交互的 Activity
    • 可见但非前台 Activity
    • 不可见后台 Activity

    内存资源不足导致 Activity 被回收,在后续也会通过 onSaveInstanceState()onRestoreInstanceState() 存储和恢复数据。
    没有四大组件在运行的进程很容易被系统杀死,所以,一些后台工作不适合脱离四大组件独自后台运行,最佳实践是依赖 Service 以保证进程有较高的优先级。

Activity 在异常情况下进行重建时,系统会默认对 View 相关的状态进行存储和恢复,具体会恢复特定 View 的什么状态数据需要去查阅源码。也就是说,非 View 相关的数据,需要自行存储和恢复。

针对上面的第一种情况,ActivityconfigChanges 可以指定一些资源配置属性,当这些资源配置发生改变之后,Activity 不会重建,不会调用 onSaveInstanceState()onRestoreInstanceState(),取而代之的是回调 onConfigurationChanged() 方法。最常用的 configChanges 选项有:

Activity 启动模式

ActivitylaunchMode 由四种:

  1. standard:默认启动方式,每次启动这样的 Activity 都会生成创建新实例。谁启动以 standardlaunchModeActivity, 该 Activity 就会运行在它的那个任务栈中
  2. singleTop:栈顶复用模式,要启动的 Activity 已经有实例在栈顶,则不会生成新实例,不会调用 onCreate()onStart() 而会调用该 ActivityonNewIntent() 方法;其他情况,参考 standard 模式;
  3. singleTask:栈内复用模式。比如 Activity A 的 TaskAffinity 属性指定的任务栈为 a,当启动 A 时,如果任务栈 a 不存在,则创建 a 任务栈,并创建 Activity A 让其入栈;如果任务栈 a 存在,且 A 实例不存在,则 A 入栈;如果任务栈 a 存在,且 A 实例存在,则清空(pop)在 A 之上的所有 Activity 让 A 置于栈顶,并回调 A 的 onNewIntent() 方法;

    TaskAffinity 即 任务相关性,这个参数标识 Activity 所需要的任务栈的名字,默认情况下,这个值是应用包名。 TaskAffinity 主要和 singleTask 启动模式配对使用,singleTask 启动模式的 Activity 会启动在 TaskAffinity 指定的任务栈中。比如:
<activity
  android:name="com.example.ExampleActivity"
  android:taskAffinity="com.exmple.exampleTask"
  android:launchMode="singleTask"/>
  1. singleInstance:单实例模式。可以看做是特殊的 singleTask 模式,除了具有 singleTask 特性外,此种模式的 Activity 只能单独在一个任务栈。

IntentFilter 匹配规则

IntentFilter 用在 Activity 的隐式调用上,先看 IntentFilter 示例:

<activity android:name="com.example.ExampleActivity">
  <intent-filter>
    <action android:name="android.intent.action.SEND" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
  </intent-filter>

  <intent-filter>
    <action android:name="android.intent.action.SEND" />
    <action android:name="android.intent.action.SEND_MULTIPLE" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="com.example.intent.category.CUSTOM_1" />
    <category android:name="com.example.intent.category.CUSTOM_2" />
    <data android:scheme="http"
      android:host="com.example.com"
      android:port="4000"
      android:path="folder"
      android:mimeType="text/plain" />
    <data android:scheme="content"
      android:host="com.example.project"
      android.port="1080"
      android:path="images"
      android:mimeType="image/*" />
  </intent-filter>
</activity>

可以看出一个 Activity 可以包含多个 IntentFilter,即形成一个 IntentFilter 列表,只要匹配任何一个 IntentFilter 就可以启动该 Activity。而 IntentFilter 中可以包含 actioncategorydata 三元素,只有这三个都匹配成功,整个 IntentFilter 才能匹配成功。

action 匹配规则

Intent 中的 action 必须和 IntentFilter 中包含的 action 之一匹配就可以匹配成功。如果,把 Intent 中指定的 action 看做元素 a,把 IntentFilter 中指定的 action 所构成的集合看成集合 A,则 当 a ∈ A 时, action 匹配成功。

category 匹配规则

  1. 如果 Intent 指定 category,就必须被包含在 IntentFilter 中所指定的 category。如果,Intent 中指定的 category 元素构成集合 A, IntentFilter 中指定的 category 元素构成集合 S,则当 A ⊆ S 时, category 匹配成功;
  2. 如果 Intent 不指定 category, 则默认的 categoryandroid.intent.category.DEFAULT, 也会匹配成功。

data 匹配规则

data 部分由 mimeTypeURI 组成,mimeType 表示媒体类型,比如图片、音频、视频、文本等格式,URI 的结构为:

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

比如:

http://com.example.com:8080/search/info
content://com.example.project:200/folder/subfolder/etc

data 的匹配规则跟 action 类似,也就是如果,把 Intent 中指定的 data 看做元素 d,把 IntentFilter 中指定的 data 元素所构成的集合看成集合 D,则 当 d ∈ D 时, data 匹配成功。

如果 data 节点中只指定了 mimeType,那么系统默认的 URIscheme 为 content 和 file。也就是说,在这种情况下,比如 intent 指定的 schemehttp 则会出现 Activity 找不到的异常。

上一篇 下一篇

猜你喜欢

热点阅读