安卓开发艺术探索一——Activity的生命周期和启动模式

Activity的生命周期和启动模式

Activity的生命周期

正常情况下的生命周期

  1. onCreate:活动正在被创建。在此方法内可以做一些初始化工作
  2. onReStart:活动正在重新启动。用户从其他活动回到当前活动时就会调用此方法。
  3. onStart:活动正在被启动。此时活动已经可见,但未出现在前台,无法和用户交互
  4. onResume:活动已经可见,并开始活动。(和onStart对比:两者都表示活动已经可见,onStart时活动还在后台,onResume时活动显示在前台)
  5. onPause:活动正在停止,正常情况下,onStop紧接着会被调用。此方法不能做耗时操作,否则会影响新活动的显示
  6. onStop:活动即将停止,此方法不能做耗时操作
  7. onDestroy:活动即将被销毁,可以做一些回收工作和资源释放

在这里插入图片描述

异常情况下的生命周期

1.系统配置改变导致活动被杀死并重新创建

在这里插入图片描述

如从竖屏切换到横屏时,系统配置发生改变导致活动被销毁,其onPause,onStop和onDestroy方法均会被调用,同时由于活动是异常终止,系统会调用onSaveInstanceState来保存当前活动的状态。这个方法调用时机是在onStop方法后,但它和onPause方法没有时序关系。活动被重新创建后,系统会调用onRestoreInstanceState方法,并把活动销毁时onSaveInstanceState方法保存的Bundle对象作为参数传给onRestoreInstanceState和onCreate方法。因此可以通过onRestoreInstanceState和onCreate两个方法来判断活动是否被重建并把保存的数据进行恢复。

保存和恢复View的层次结构,系统的工作流程类似与View对事件的分发:首先活动被意外终止时,它会调用onSaveInstanceState来保存数据,然后Activity委托Window保存数据,接着Window再委托它上面的顶级容器保存数据,顶层容器一般为DecorView。最后像View对事件的分发一样,顶层容器一一通知它的子元素保存数据。

可以指定Activity中的configChanges属性,使系统配置发生变化时,不重建Activity
在AndroMenifest.xml的Activity声明configChanges的值,可以在系统配置发生改变时,使系统不会重建该Activity。常用的
configChanges属性:locale(设备本地位置发生变化) orientation(屏幕方向发生变化)和keyboardHidden(隐藏键盘)这三个选项

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

首先看一下Activity的优先级,优先级由高到低分为三种:

(1) 前台Activity:正在和用户交互的活动,优先级最高

(2) 可见但非前台Activity:如Activity中弹出了一个对话框,导致Activity可见但位于后台,无法和用户直接交互。

(3) 后台Activity:已经被暂停的活动,如执行力onStop,优先级最低

当系统内存不足时,就会按照上面的优先级杀死目标活动所在进程,并在后续通过onSaveInstanceState和onRestoreInstanceState储存和恢复数据。

Activity的启动模式

  1. standard:标准模式,也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。被创建的实例的生命周期符合典型情况下Activity的生命周期,其onCreate,onStart,onResume都会被调用。例如从A活动多次跳转到B活动再跳转回来,此时已经创建了很多个A活动的实例,要从A活动退出,就需要多次返回才能退出。
  2. singleTop:栈顶复用模式。在这种模式下,如果新Activity已经位于任务栈顶,那么此Activity不会被创建,同时它的onNewIntent方法会被回调,通过此方法的参数可以取出当前请求的信息。需要注意的是:此Activity的onCreate,onStart和onResume方法不会被系统调用,因为它没有发生改变。如果新Activity不是位于栈顶,则新Activity仍然会重新创建。
  3. singleTask:栈内复用模式。这是一种单实例模式,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调其onNewIntent。当一个singleTask模式的活动请求启动后,系统会首先寻找是否存在该活动想要的任务栈,如果不存在,则会先重新创建一个任务栈,再创建该活动的实例并将其放到栈中;如果已经存在,要看该活动是否在栈中有实例存在,如果有,系统会把该活动调到栈顶并调用其onNewIntent方法,并且该活动上面的所有活动将会出栈,否则,创建该活动的实例并将其压入栈中。
  4. singleInstance:单实例模式。加强版的singleTask模式,除了singleTask的所有特性外,具有此模式的活动只能单独位于一个任务栈中。

启动模式的设置

1.在AndroidMenifest.xml中的activity标签中加入android:launchMode属性,值为上面四种模式之一

2.在Intent中通过标志位指定,例如:

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

两种设置方式有一定的区别:首先,第二种的优先级高于第一种;其次,两者在限定范围上有不同

常用的Flags

FLAG_ACTIVITY_NEW_TASK
这个标记位作用是为Activity指定“singleTask”启动模式
FLAG_ACTIVITY_SINGLE_TOP
这个标记位作用是为Activity指定“singleTop”的启动模式
FLAG_ACTIVITY_CLEAR_TOP
具有此标记位的Activity,当他启动时在同一个任务栈中所有位于他上面的Activity都有出栈。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标志的Activity,不会出现在历史Activity列表中

IntentFilter的匹配规则

概述

为了匹配过滤列表,需要同时匹配过滤列表中的action,category,data三项信息,否则匹配失败。一个过滤列表中的action,category,data可以有多个。另外,一个活动可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应Activity。

1.action的匹配规则

action是一个字符串,Intent中的action必须能和过滤规则中的action匹配,即和action的字符串值完全一样。一个活动可以有多个过滤规则,一个过滤规则可以有多个action,只要Intent中的action能和任一过滤规则中任一action相同即可匹配成功,否则匹配失败。另外,action区分大小写;系统预定义了一些action,我们也可以使用自定义action。再有,如果action匹配了多个activity,系统会提示从多个activity中选择一个打开,如下图所示;如果匹配了一个activity就会直接跳转到该活动。

在这里插入图片描述

**在Intent中设置action:**intent.setAction(String string)

2.category的匹配规则

category也是字符串,系统也预定义了一些category,也可以自定义。其匹配规则和action不同,如果Intent中如果含有category,那么所有的category都必须和过滤规则中的其中一个category相同。即如果Intent中出现了category,不管有几个,对于每个category都必须是过滤规则中已经定义了的。另外,如果Intent中没有category,则默认匹配成功;系统在调用startActivity或StartActivityForResult会默认为Intent加上”abdroid.intent.category.DEEAULT”这个category。所以为了我们的Activity能够隐式调用Activity,就必须在intent-filter中指定“abdroid.intent.category.DEEAULT”这个category。

**在Intent中设置category:**intent.addCategory(String category)

3.data的匹配规则

首先来了解data的语法:
在这里插入图片描述

data由两部分组成:mimeType(媒体类型,如image,jpeg等)和URI,URI包含的数据较多,其结构如下:

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

每个数据的含义

Scheme:URI的模式,比如https,file,content等,如果URI没有指定scheme,则整个URI的其他参数无效,即URI无效。

Host:URI的主机名,如www.baidu.com,如果host未指定,那么URI的其他参数无效,即URI无效。

Port:端口号,如8080,仅当URI中制定了scheme和host参数时port参数才有意义。

Path,pathPattern和pathPrefix:这三个参数表述路径信息,其中path表示完整路径信息,pathpattern也表示完整信息,但是他的可以包含通配符 “*”。pathPrefix表示路径的前缀信息

data的匹配规则和action类似,它要求Intent中必须含有data数据,并且data数据能够完全匹配过滤规则中的某一个data

**给Intent中同时设置data和type只能用函数setDataAndType:**setDataAndType(Uri data, String type)

设置data:setData(Uri data) 设置type:setType(String type)

最后,当我们通过隐式方式启动一个活动时可以通过PackageManager或Intent的resolveActivity方法判断能否匹配Activity,如果找不到匹配的就返回null

参考资料

《安卓开发艺术探索》

发布了14 篇原创文章 · 获赞 4 · 访问量 686

猜你喜欢

转载自blog.csdn.net/qq_43935080/article/details/104001407