[Android开发艺术探索阅读笔记]第1章 Activity的生命周期和启动模式

生命周期

正常情况

onStart和onResume、onPause和onStop从描述上来看差不多,对我们来说有什么实质的不同呢?

onStart和onStop区分是否可见,onResume和onPause区分是否在前台。

假设当前Activity为A,如果这时用户打开一个新Activity B,那么B的onResume和A的onPause哪个先执行呢?

执行顺序为:

A-onPause
B-onCreate
B-onStart
B-onResume
A-onStop
复制代码

onPause()和onStop()不能做耗时的操作,尽量在onStop中做一些保存操作,使得下一个Activity尽快显示出来。

异常情况

情况1:资源相关的系统配置发生改变导致Activity被杀死并重新创建

当系统配置发生改变后,Activity会被销毁,其onPause、onStop、onDestroy均会被调用。
系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法的调用时机是在onStop之前,它和onPause没有既定的时序关系,它既可能在on-Pause之前调用,也可能在onPause之后调用。需要强调的一点是,这个方法只会出现在Activity被异常终止的情况下,正常情况下系统不会回调这个方法。当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时on-SaveInstanceState方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。因此,我们可以通过onRestoreIn-stanceState和onCreate方法来判断Activity是否被重建了,如果被重建了,那么我们就可以取出之前保存的数据并恢复,从时序上来说,onRestoreInstanceState的调用时机在onStart之后。

如屏幕旋转会触发这种情况。

系统配置中有很多内容,如果当某项内容发生改变后,我们不想系统重新创建Activity,可以给Activity指定configChanges属性,然后我们自己在Activity的onConfigurationChanged方法中处理自己的逻辑。

情况2:资源内存不足导致低优先级的Activity被杀死

Activity按照优先级从高到低,可以分为如下三种:

  1. 前台Activity——正在和用户交互的Activity,优先级最高。
  2. 可见但非前台Activity——比如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和用户直接交互。
  3. 后台Activity——已经被暂停的Activity,比如执行了onStop,优先级最低。

当系统内存不足时,系统就会按照上述优先级去杀死目标Activity所在的进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数数据。如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此,一些后台工作不适合脱离四大组件而独自运行在后台中,这样进程很容易被杀死。比较好的方法是将后台工作放入Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。

启动模式

使用清单文件

在清单文件中声明 Activity 时,您可以使用 元素的 launchMode 属性指定 Activity 应该如何与任务关联。

launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:

  1. "standard"(默认模式)
  2. "singleTop"
  3. "singleTask"
  4. "singleInstance"

使用 Intent 标志

  1. FLAG_ACTIVITY_NEW_TASK :

    指定singleTask模式

  2. FLAG_ACTIVITY_SINGLE_TOP :

    指定singleTop启动模式

  3. FLAG_ACTIVITY_CLEAR_TOP :

    使其Activity之上的所有Activity都出栈。一般和 FLAG_ACTIVITY_NEW_TASK配合使用,如果Ativity实例已经存在,系统会调用他的onNewIntent。若和standard模式配合使用,那么它和它之上的所有Activity都要出栈,系统会创建新的实例放到栈顶。singleTask默认就有此标记的效果。

  4. FLAG_ACTIVITY_EXCLUDE_FROM_RE-CENTS :

    具有这个标记的Activity不会出现在历史Ac-tivity的列表中,等同于android:excludeFromRecents="true"

使用方法: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

任务栈关联

taskAffinity 与 allowTaskReparenting

默认值是包名,需要和allowTaskReparenting或者singleTask配对使用。

当 taskAffinity 和 singleTask 配合使用时,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中。

当 taskAffinity 和 allowTaskReparenting 配合使用时,如果allowTaskReparenting为true,应用A启动了应用B的Activty C,按Home键回到桌面,再单击B的桌面图标,显示的是Activity C,而不是显示B的主Activity,C从A的任务栈转移到了B的任务栈中。

实践

上图 B 启动 C ,情况会如何?

清单文件:

<application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
    <activity
        android:name=".ActivityC"
        android:launchMode="singleTask">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>

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

    <activity
        android:name=".ActivityA"
        android:launchMode="singleTask"
        android:taskAffinity="com.task"
        />
    <activity
        android:name=".ActivityB"
        android:launchMode="singleTask"
        android:taskAffinity="com.task"
        />

  </application>
复制代码

调用顺序 C->D->A->B->C

结果返回栈中是 A->B->C,D被直接出栈。

singleTask模式的Activity切换到栈顶会导致在它之上的栈内的Activity出栈。

IntentFilter 匹配规则

启动Activity分为显示调用和隐式调用,隐式调用需要Intent去匹配IntentFilter中所设置的过滤信息。

例:

 <activity
        android:name="com.ryg.chapter_1.ThirdActivity"
        android:configChanges="screenLayout"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:taskAffinity="com.ryg.task1">
      <intent-filter>
        <action android:name="com.ryg.charpter_1.c"/>
        <action android:name="com.ryg.charpter_1.d"/>

        <category android:name="com.ryg.category.c"/>
        <category android:name="com.ryg.category.d"/>
        <category android:name="android.intent.category.DEFAULT"/>

        <data android:mimeType="text/plain"/>
      </intent-filter>
    </activity>
  
复制代码

只有一个Intent同时匹配action类别、cat-egory类别、data类别才算完全匹配,只有完全匹配才能成功启动目标Activity。

一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应的Activity。

action 的匹配规则

只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功。

category 的匹配规则

要求Intent中如果含有category,那么所有的category都必须和过滤规则中的其中一个category相同。

data 的匹配规则


    <data
        android:host="string"
        android:mimeType="string"
        android:path="string"
        android:pathPattern="string"
        android:pathPrefix="string"
        android:port="string"
        android:scheme="string"/>
复制代码

URI结构: <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>

例:
content://com.example.project:200/folder/subfolder/etc

http://www.baidu.com:80/search/info

参考

Android开发艺术探索

Develop API Guides 应用组件

Intent 和 Intent 过滤器

任务和返回栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值