Activity生命周期和启动模式

1.1 Activity的生命周期全面分析

典型情况下:

normal

异常情况下:

accident

需要注意的点:

  • onStart和onResume、onPause和onStop从描述上差不多,其本质的区别:onStart和onStop是从Activity是否可见的角度来回调的,onResume和onPause是从Activity是否在前台的角度来回调的。
  • 从ActivityA跳转到ActivityB时,是要先调用A的onPause后,才真正开始启动ActivityB。
  • 当我们在onSaveInstanceState保存一些数据时,意外情况下,我们可以通过onCreate或者onRestoreInstanceState进行数据恢复,其区别是onRestoreInstanceState一旦被调用其参数Bundle savedInstanceState一定是有值的,我们不需要额外判断是否为空;而onCreate正常情况下,其参数Bundle savedInstanceState是为null的,所以需要进行额外判断。虽然2个方法都可行,但是官方建议使用onRestoreInstanceState去恢复数据。

1.2 Activity的启动模式

1.2.1 Activity的LaunchMode

  • standard—标准模式,系统默认模式。每次启动都会新建一个新的实例。被启动的activity会运行启动它的activity的任务栈上。如果用ApplicationContext去启动,则会报错,因为这是一个非Activity类型的Context,不存在任务栈,所以如果要解决,则需要为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK的标记位。
  • singleTop—栈顶复用模式。如果启动的Activity在栈顶时,则不会新建新的实例。
  • singleTask—栈内复用模式。如果启动的Activity在栈内时,则不会新建新的实例。启动此模式下的Actvity时,默认具有clearTop效果。例:ActivityB 为singleTask模式,当前栈内情况:ABCD,此时启动B的话,则栈内情况变为:AB。
  • singleInstance—单实例模式。除了具有singleTask模式的所有特性外,还有一点,就是具有此模式的Activity只能单独地位于一个任务栈中。

需要注意的点:

  • TaskAffinity:该参数表示了一个Activity任务栈的名字。默认情况下为包名。该属性主要和singleTask或allowTaskReparenting配对使用,其他情况下无意义。
  • TaskAffinity和singleTask配对使用时,待启动的Activity会运行在TaskAffinity指定的任务栈当中。
  • TaskAffinity和allowTaskReparenting配对使用时。当一个应用A启动了应用B的某个Activity C时,如果Activity C的allowTaskReparenting属性为true时,那么当应用B启动时,Activity C会从A的任务栈转移到B的任务栈当中

Activity的启动模式有两种指定方法:

一种是通过AndroidManifest,如下:

<activity
    android:name=".activity.MainActivity"
    android:launchMode="singleTask"/>

另一种是通过intent设置标志位,如下:

Intent intent = new Intent(mContext,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

两者之间的区别:

  • 第二种优先级高于第一种
  • 第一种无法直接实现FLAG_ACTIVITY_CLEAR_TOP标识
  • 第二种无法为Activity指定singleInstance模式

1.2.2 Activity的Flags

几个常用的Flags:

  • FLAG_ACTIVITY_NEW_TASK

    指定Activity为“singleTask”启动模式,与xml效果一致

  • FLAG_ACTIVITY_SINGLE_TOP

    指定Activity为“singleTop”启动模式,与xml效果一致

  • FLAG_ACTIVITY_CLEAR_TOP

    使用此标记启动的Activity会将其所在的任务栈中,所有位于它上方的Activity都出栈。

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

    使用此标记启动的Activity不会出现在历史的Activity列表中,等同于在xml中,指定Activity的属性android:excludeFromRecents="true"

1.3 IntentFilter的匹配规则

  • action

    action是一个字符串,系统预定义了一些action,同时我们也可以在应用中自定义action。只有当intent中的action与过滤规则中的action值完全一样(区分大小写)才算是匹配。一个过滤规则中可以有多个action,而intent中的action只需要与过滤规则中的任意一个action相同即可匹配成功。

  • category

    category是一个字符串,系统预定义了一些category,同时我们也可以在应用中自定义category。如果intent中含有category,那么每一个category都需要与过滤规则中的其中一个category相同才能匹配成功。

    注意:intent中可以没有category,因为系统在startActivity或startActivityForResult时默认会加上“android.intent.category.DEFAULT”,所以如果一个activity要接受一个隐式调用就必须要在intent-filter上指定“android.intent.category.DEFAULT”这个category。

  • data

    结构如下:

    <data
        android:scheme=""
        android:host=""
        android:port=""
        android:path=""
        android:pathPattern=""
        android:pathPrefix=""
        android:mimeType=""/>
    

    data匹配规则与action类似。data由两部分组成,mimeType和URI。

    Intent中如果没有指定URI,则默认值为content和file。

需要注意的点:

​ 当我们隐式启动activity时,如果没有匹配的activity,则会报错提示找不到Activity。所以我们需要在启动前判断一样是否有匹配的Activity提供我们启动。

​ 判断方法有2种:一是通过PackageManager的resolveActivity或Intent的resolveActivity方法,如果找不到则会返回null。二是通过PackageManager提供的queryIntentActivities方法,该方法不是返回最佳匹配的Activity而是返回所有成功匹配的Activity。

版权声明:

本文标题:Activity生命周期和启动模式

作者:Rabtman

原始链接:https://rabtman.com/2016/08/03/note_android_lifecycle_launchmode/

本文采用署名-非商业性使用-禁止演绎4.0进行许可。

非商业转载请保留以上信息。商业转载请联系作者本人。