Android生命周期与启动模式

Android 生命周期与启动模式

1.1 Android 生命周期

参考资料:
https://www.gitbook.com/book/tom510230/android_ka_fa_yi_shu_tan_suo/details
官方文档

生命周期分为两部分:一部分是典型(正常)的生命周期,用户参与下所经历的生命周期,比如手动启动Activity和销毁Activity。另一部分是异常情况下的生命周期,比如Activity被系统回收或设备Configuration发生变化导致的Activity被销毁重建。

1.1.1 典型情况的生命周期

说明:

  1. 第一次启动某一个Activity回调:onCreate->onStart->onResume;
  2. back键退出当前Activity回调:onPause->onStop->onDestory;
  3. home键或打开新的Activity回调:onPause->onStop,如果Activity采用透明主题,则不会调用onStop。
  4. 再次回到原Activity回调:onRestart->onStart->onResume;
  5. 打开新的Activity回调:A:onPause-> B:onCreate-> B:onStart-> B:onResume-> A:onStop

    说明:旧的Activity的onPause先调用,然后新的Activity才启动,所以在onPause中要避免做重量级操作,在官方文档中有体现:

1.1.2 异常情况下的生命周期分析

1. 资源相关的系统配置发生改变导致Activity被杀死

旋转屏幕等会导致系统配置发生变化,默认情况下,Activity会被销毁并且重新创建,也可以人为的阻止系统重建。
在默认情况下,不对Activity做任何处理,那么系统变化后,会被销毁和重建:生命周期如下:

只有在异常情况下(在home或启动其他Activity的时候也会单独调用onSaveInstanceState),Activity会在onStop之前调用onSaveInstanceState,与onPause无特定顺序,当Activity被重新创建的时候,系统会在onStart之后调用onRestoreInstanceState,并把Activity销毁时保存的bundle数据作为参数传给onRestoreInstanceState。

关于数据保存和恢复,Activity调用onSaveInstanceState保存数据--> Activity委托Window保存数据--> Window委托顶级容器(ViewGroup,可能是DecorView)保存数据--> ViewGroup通知子元素保存数据。这是一种典型的委托模式,典型的委托模式还有View绘制过程事件分发等。

上面被销毁并进行了重建,那什么情况下不会被重建呢?
如果不想被重建,那么可以给Activity指定configChange属性:比如android:configChanges=”orientation”屏幕旋转的时候不会进行重建,也不会调用onSaveInstanceState和onRestoreInstanceState,而是调用onConfigurationChanged方法。
配置常见的有三种:locale、orientation、keyboardHidden

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

Activity优先级从高到低:

  1. 前台Activity--正在与用户进行交互的Activity优先级最高。
  2. 可见但非前台Activity--弹出对话框等导致的Activity可见但无法交互。
  3. 后台Activity--已经被暂停的Activity,比如执行了onStop(切在后台),优先级最低。

1.2 Activity的启动模式

1.2.1 Activity的LuncherMode
  1. standard:标准、默认模式,不管在栈中是否存在,都会创建Activity实例在启动它的Activity所在的栈中。需要注意:创建的实例默认会在启动它的Activity所在的栈中,那么,非Activity的Context(ApplicationContext)并不存在所谓的任务栈,所以会报错,解决方法就是为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标志位,启动的时候为其创建一个任务栈,而添加了FLAG_ACTIVITY_NEW_TASK的Flag,实际就变成了以singleTask模式启动。后面会说到Flag。
  2. singleTop:栈顶复用模式,如果新的Activity在栈顶,则不会创建,同时回调onNewIntent,onCreate、onStart不会被回调,因为Activity没有创建。
  3. singleTask: 栈内复用模式,单实例模式,只要Activity在一个栈中存在,那多次启动都不会创建Activity,会回调onNewIntent,同时要启动的Activity之上的Activity全部被清除出栈,如果不存在,则重新创建一个任务栈,然后创建Activity放入栈中。
  4. singleInstance:单实例模式,加强版singleTask,此模式的Activity单独位于一个任务栈中。

TaskAffinity的运用

1.2.2 Activity的Flags

标记位一般与启动模式相关,会影响Activity的运行状态。
常见的几种Flags:

  1. FLAG_ACTIVITY_NEW_TASK:其效果等同于为Activity指定“singleTask”的启动模式。
  2. FLAG_AVCTIVITY_SINGLE_TOP:其效果等同于为Activity设置“singleTop”的启动模式。
  3. FLAG_ACTIVITY_CLEAR_TOP:清除同一任务栈中位于它上面的Activity,一般与FLAG_ACTIVITY_NEW_TASK配合使用,被启动的Activity如果已存在,那么就会调用onNewIntent方法,如果被启动的Activity使用standard模式,那它连同他之上的都要出栈,会重新创建实例,放入栈顶。
  4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有此标记位的Activity不会出现在历史Activity列表中(Android 多任务管理器查看的时候不会显示),等同于xml中指定Activity属性为:android:excludeFromRecents=”true”;

官方文档:Intent-Flags

1.3 IntentFilter的匹配规则

启动Activity分为两种:显式调用和隐式调用。显式调用明确指定被启动对象的组件信息,包括类名和包名。隐式调用根据过滤信息进行匹配,同时使用隐式和显式时,以显式为主。匹配的信息:action、category、data,可以有多组intent-filter,只有同时匹配一组才能启动目标Activity。
1. action: action的字符串完全一致才算匹配成功,区分大小写,一组intent-filter可以有多个action,匹配一个就算成功。
2. category: category是一个字符串,系统预定义了一些category,Intent可以没有category,如果有,不管几个,都必须和intent-filter过滤规则中的category匹配。不设置可以匹配是因为在startActivity或startActivityForResult的时候会默认添加“android.intent.category.DEFAULT”这个category。
3. data: data的匹配规则与action类似,data由两部分组成:mimeType和URI。mimeType指媒体类型,比如image/jepg、audio/mpeg4-generic和video/*等,可以表示图片文本视频等不同媒体类型,而URI包含的数据比较多,大致结构:

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

结合实例:

    content://com.example.project:200/folder/subfolder/etc
    http://www.baidu.com:80/search/info

Scheme: URI的模式,比如http、file,没有指定,其他参数无效,URI无效。
Host: URI的主机,比如www.baidu.com,未指定,其他参数无效,URI无效。
Port: URI中的端口号,比如80,指定了Scheme和Host,Port才有效。
Path、pathPattern、pathPrefix: 表示路径信息,path、pathPattern表示完整路径,可以包含通配符*,表示0或多个任意字符,pathPrefix表示路径的前缀信息。

例子:

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

隐式意图注意内容:

通过隐式意图启动Activity的时候,可以做一下判断,看是否有 Activity匹配到隐式意图,不做判断,匹配不到可能会出现ActivityNotFoundException异常,判断的方式:PackageManager的resolveActivity或着Intent的resolveActivity,另外PackageManager提供了queryIntentActivities方法,返回值是所有匹配的Activity信息。

    public abstract List<ResolveInfo> queryIntentActivities(Intent intent,@ResolveInfoFlags int flags);
    public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);

需要注意的是,第二个参数使用MATCH_DEFAULT_ONLY 仅仅匹配在intent-filter中声明了android.intent.category.DEFAULT的category的Activity,意义在于,只要不返回null,那么startActivity一定会成功。

还有一类action和category比较重要:

    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />

二者共同作用,表明这是程序入口的Activity并且出现在系统应用列表中,二者缺一不可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值