《Android开发艺术探究》——第一章:Activity的生命周期和启动模式

作者 : 开心源码 本文共6021个字,预计阅读时间需要16分钟 发布时间: 2022-05-12 共147人阅读

目录

  • Activity生命周期全面分析
  • Activity的启动模式
  • Intent的匹配规则

Activity生命周期全面分析

典型情况是指客户参加的情况下,Activity所经过的生命周期的变化;

异常情况是指Activity被系统回收或者者因为当前设施的Configuration发生改变从而导致Activity被销毁重建。

典型情况下的生命周期分析

onCreate:表示Activity正在被创立,这是生命周期的第一个方法,在这个方法中,我们可以做少量初始化的工作,比方调用onContentView去加载界面布局资源,初始化Activity所需数据等。

onRestart:表示Activity正在重新启动,一般情况下,当当前Activity从不可见重新变为可见时,onRestart就会被调用,这总情况一般是客户行为所导致的,比方客户按home键切换到桌面或者者客户打开了一个新的Activity,这时当前的Activity就会被暂停,也就是onPause和onStop方法被执行了,接着客户又回到了这个Activity,就会出现这种情况。

onStart:表示Activity正在被启动,即将开始,这个时候Activity已经可见了,但是还没有出现在前端,还无法和客户交互,这个时候我们可以了解为Activity已经启动了,但是我们还没有看见。

onResume:表示Activity已经可见了,并且出现在前端,并开始活动了,要注意这个和onStart的比照,这两个都表示Activity已经可见了,但是onStart的时候Activity还处于后端,onResume的时候Activity才显示到前端。

onPause:表示Activity正在中止,正常情况下,紧接着onStop就会被调用,在特殊情况下,假如这个时候再快速的回到当前Activity,那么onResume就会被调用。此时可以做少量数据存储,中止动画等工作,但是注意不要太耗时了,由于这样会影响到新的Activity的显示,onPause必需先执行完,新Activity的onResume才会执行。

onStop:表示Activity即将中止,同样可以做少量轻量级的资源回收,但是不要太耗时了。

onDestroy:表示Activity即将被销毁,这是Activity生命周期的最后一个回调,在这里我们可以做少量最后的回收工作和资源释放。

Activity生命周期的切换过程

具体场景说明:

1.针对一个特定的Activity,第一次启动,回调如下:onCreate ——> onStart ——> onResume。

2.当客户打开新的Activity或者者切换到桌面的时候,回调如下:onPause ——> onStop ——> 这里有一种特殊的情况就是,假如新的Activity采取了透明的主题的话,那么当前Activity不会回调onStop。

3.当客户再次回到原来的Activity,回调如下:onRestart ——> onStart ——> onResume。

4.当客户按back键的时候回调如下:onPause ———> onStop ——> onDestroy。

5.当Activity被系统回收的时候再次打开,生命周期回调方法和1是一样的,但是你要注意一下就是只是生命周期一样,不代表所有的进程都是一样的,这个问题等下回详细分析。

6.从整个生命周期来说,onCreate和onDestroy是配套的,分别标示着Activity的创立和销毁,并且只可能有一次调用,从Activity能否可见来说,onStart和onStop是配套的,随着客户的操作和设施屏幕的点亮和熄灭,这两个方法可能被调用屡次,从Activity能否在前端来说,onResume和onPause是配套的,随着客户操作或者者设施的点亮和熄灭,这两个方法可能被屡次调用。

这里提出两个问题:

1.onStart和onResume,onPause和onStop从形容上都差不多,对我们来说有什么实质性的不同呢?

答:onStart和onStop是从Activity能否可见这个角度来回调的,而onResume和onPause是从Activity能否位于前端这个角度来回调的,除了这种区别,在实际的使用中,没有其余显著的区别。

2.假设当前Activity为A,假如客户打开了一个新的Activity为B,那么B的onResume和A的onPause谁先执行尼?

答:当新的Activity启动的时候,旧的Activity的onPause方法会先执行,而后才启动新的Activity。也就是说,不能在onPause中做重量级的操作,由于必需在onPause执行完成以后新的Activity才能Resume。

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

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

比方当前Activity处于竖屏,我们忽然旋转屏幕,因为系统配置发生了改变,在默认情况下,Activity会被销毁并且重新创立,当然我们也可以阻止系统重新创立我们的Activity。

默认情况下,假如我们的Activity不做特殊解决,那么当系统配置发生改变之后,Activity就会销毁并且重新创立,可以看图:

异常情况下Activity的重建过程

当系统配置发生改变的时候,Activity会被销毁,其onPause,onStop,onDestroy均会被调用,同时因为Activity是异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态,这个方法调用的时机是在onStop之前,他和onPause没有既定的时序关系,他就可能在onPause之前调用,也有可能在之后调用。

当我们onSaveInstanceState保存到Bundler对象作为参数传递给onRestoreInstanceState和onCreate方法,因而我们可以通过onRestoreInstanceState和onCreate方法来判断Activity能否被重建。假如被重建了,我们就取出之前的数据恢复,从时序上来说,onRestoreInstanceState的调用时机应该在onStart之后。

这里可以简单的这么了解,系统只在Activity异常终止的情况下才会调用onSaveInstanceState和onRestoreInstanceState来存储和恢复数据,其余情况不会触发。

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

Activity按照优先级的从高往低,可以分为三种:

  1. 前端Activity:正在和客户交互的Activity,优先级最高。
  2. 可见但非前端Activity:比方对话框,导致Activity可见但是位于后端无法和客户直接交互。
  3. 后端Activity:已经被暂停的Activity,比方执行了onStop,优先级最低。

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

Activity的启动模式

Activity的LaunchMode

standard

standard:标准模式,这也是系统的默认模式,每次启动一个Activity都会重新创立一个实例,能否这个实例已经存在。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的Activity所在的栈内。

当我们用ApplicationContext去启动standard模式的Activity的时候就会报错,由于我们的standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是因为非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,所以这就有问题了,处理这个问题,就是待启动Activity指定FLAG_ACTIVITY_TASK标记位,这样启动的时候就会为他创立一个新的任务栈,这个时候待启动Activity实际上是以singleTask模式启动的。

singleTop

singleTop:栈顶复用模式,在这个模式下,假如新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创立,同时他的onNewIntent方法会被调用,通过此方法的参数我们可以取出当前请求的信息,需要注意的是,这个Activity的onCreate,onStart不会被系统调用,由于他并没有发生改变。

singTask

singTask:栈内复用模式,这是一种单实例模式,在这种模式下,只需Activity在一个栈内存在,那么屡次启动此Activity都不会创立实例,和singTop一样,系统也会回调其onNewIntent方法。

singleInstance

singleInstance:单实例模式,这是一种增强的singleTask的模式,他除了具备singleTask的所有属性之外,还增强了一点,那就是具备此模式下的Activity只能单独的处于一个任务栈中,换句话说,比方ActivityA是singleInstance模式,当A启动的时候,系统会为创立创立一个新的任务栈,而后A独立在这个任务栈中,因为栈内复用的特性,后续的请求均不会创立新的Activity,除非这个独特的任务栈被系统销毁了。

如何给Activity指定启动模式?

有两种方法,第一种是通过清单文件为Activity指定

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

另一种启情况就是通过intent的标志位为Activity指定启动模式

Intent intent = new Intent();intent.setClass(this,SecondActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);

Activity 的 Flags

FLAG_ACTIVITY_NEW_TASK

这个标志位的作用是为Activity指向‘singleTask’启动模式,其效果和XML中指定该模式相同

FLAG_ACTIVITY_SINGLE_TOP

这个标志位的作用是为Activity指向‘singleTop’启动模式,其效果和XML中指定该模式相同

FLAG_ACTIVITY_CLEAR_TOP

具备此标记位的Activity,当他启动时,在同一个任务栈中所有位于他上面的Activity都要出栈,这个模式一般需要和FLAG_ ACTIVITY_ NEW _ TASK配合使用,在这种情况下,被启动的Activity的实例假如已经存在,那么系统就会调用它的onNewIntent,假如被启动的Activity采用标准模式,那么他连同他之上的Activity都要出栈,系统会创立新的Activity实例并放入栈顶

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具备此标记位的Activity,不会出现在历史Activity的列表当中,当某种情况下我们不希望客户通过历史列表回到我们的Activity的时候就使用这个标记位了,他等同于在XML中指定Activity的属性: android:excludeFromRecents=”true”

intentFilter的匹配规则

我们知道,启动Activity分为两种,显示调用和隐式调用,二者的区别这里就不多讲了,显示调用需要明确的指定被启动对象的组件信息,包括包名和类名,而隐式用意则不需要明确指定调用信息,准则上一个intent不应该即是显式调用又是隐式调用,假如二者共存的话以显式调用为主,显式调用很简单,这里主要详情隐式调用,隐式调用需要intent能够匹配目标组件的IntentFilter中所设置的过滤信息,假如不匹配将无法启动目标Activity,IntentFilter中的过滤信息有action,category,data,下面是一个过滤规则的实例:

        <activity            android:name=".CodeActivity"            android:configChanges="screenLayout"            android:launchMode="singleTask"            android:taskAffinity="com.liuguilin.activitysample1">            <intent-filter>                <action android:name="com.liuguilin.activitysample.c" />                <action android:name="com.liuguilin.activitysample.d" />                <category android:name="com.liuguilin.category.c" />                <category android:name="com.liuguilin.category.d" />                <data android:mimeType="text/plain" />            </intent-filter>        </activity>

只有一个intent同时匹配action类别,category类别,data类别才算是匹配完成,只有完全匹配才能成功启动目标Activity。

1.action的匹配规则

action的匹配需求就是intent中的action存在且必和过滤规则一样的action,这里需要注意的是他和category匹配规则的不同,另外,action区分大小写,大小写不同的字符串匹配也会失败。

2.category的匹配规则

category的匹配规则和action不同,它要求Intent中假如含有category,那么所有的category都必需和过滤规则中的其中一个category相同。

Intent中可以没有category,起因是系统在调用startActivity或者者startActivityForResult的时候会默认为Intent加上“android.intent.category.DEFAULT”这个category。

3.data匹配规则

data的匹配规则和action相似,它也要求Intent中必需含有data数据,并且data数据能够完全匹配过滤规则中的某一个data.这里的完全匹配是指过滤规则中出现的data部分也出现在了Intent中的data中。

参考资料:

《Android开发艺术探究》

Android开发艺术探究笔记

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 《Android开发艺术探究》——第一章:Activity的生命周期和启动模式

发表回复