Activity生命周期全面分析

1.典型情况下的生命周期

这里写图片描述

从整个生命周期来说,onCreate和onDestroy 是配对的,分别标志着Activity创建和销毁,并且只可能调用一次。
从Activity 是否可见来说onStrart 和onStop 是配对的,随着用户的操作或设备的屏幕的点亮和熄灭,被调用多次。
从Activity 是否在前台来说 onResume 和onRause 是配对的,随着用户的操作或设备的屏幕的点亮和熄灭,被调用多次。

2.异常情况下的生命周期

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

拿最简单的图片来说,当我们把一张图片放在drawable目录后,就可以通过Resources去获取这张图片。同时为了兼容不同设备,我们可能需要放置不同的图片,比如drawable-mdpi、drawable-hdpi、drawable-land等。这样,当应用程序启动时,系统会根据当前设备的情况去加载合适的Resources资源,比如说横屏手机和竖屏手机会拿到两张不同的图片。比如说当前Activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建(当然我们也可以阻止系统重新创建我们的Activity)

在默认情况下,如果我们的Activity不做特殊处理,那么当系统配置发生改变后,Activity就会被销毁并重新创建,如下图
这里写图片描述

当系统配置发生改变后,Activity会被销毁。其onPause,onStop,onDestroy均会被调用,同时由于Activity是在异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity 的状态。(在onStop之前调,在onPause之前或之后调用)。

注意:onSaveInstanceState 方法只会出现在Activity被异常终止的情况下

当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState 方法所保存的Bundle 对象作为参数同时传递给onRestoreInstanceState和onCreate方法。因此,我们可以通过onRestoreInstanceState 和 onCreate方法来判断Activity是否被重建了,如果被重建了,我们可以取出之前保存的数据并恢复(从时序上说,onRestoreInstanseState的调用时机在onStart之后)

当Activity在异常情况下需要重新创建时,系统会默认为我们保存当前Activity的视图结构,并在activity重启后为我们恢复这些数据,比如文本款中用户输入的数据、ListView滚动的位置等,这些View相关的状态系统都能够默认为我们恢复

保存和恢复View层次结构,系统工作流程:当Activity被意外终止时,Activity会调用onSaveInatanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶级容器去保存数据。顶层容器是一个ViewGroup,一般来说他很可能是DecorView .最后顶层容器再去一一通知它的子元素来保存数据。(委托思想)如下图

这里写图片描述

这说明系统的确能够自动的做一些View层次结构方面的数据存储和恢复,下面再用一个例子,来验证我们自己做数据存储和恢复的情况,如下图
这里写图片描述
上诉代码首先在onSaveInatanceState中存储一个字符串,然后当Activity被销毁并重新创建后,我们再去获取之前存粗的字符串。接收的位置可以选择onRestoreInstanceState 和 onCreate 。
二者区别:onRestoreInstanceState 一旦被调用,其参数savedInstanceState一定有值,不需额外去判断是否为空;onCreate 正常启动时参数savedInstanceState为空,所以必须要额外判断。

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

这种情况不好模拟,但是其数据存粗和恢复过程和情况1完全一样
Activity优先级按照优先级从高到低,可分为三种情况

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

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

上述分析了系统的数据存储和恢复机制,我们知道,当系统配置发生改变后,Activity会被重新创建,那么有没有办法不重新创建呢?
如果我们不想重新创建Activity,可以给Activity指定configChanges属性。如不想让屏幕旋转后重新创建Activity可以给 configChanges 属性添加 orientation这个值4

这里写图片描述

Activity 的启动模式

  1. standard :标准模式,这也是系统默认模式,每次启动一个Activity都会重新创建一个新的实例。被创建的Activity的 onCreate、onStrat、onResume会被调用。这是一种典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。例如Activity A启动了Activity B (B是标准模式),那么B就会进入到A所在的栈中
  2. singleTop:栈顶复用模式:如果新Activity位于栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被回调。此时这个Activity的onCreate、onStart不会被调用,因为他没有发生改变。如果新的Activity的实例已存在但不是 位于栈顶,那么新的Activity 任然会被创建。
  3. singleTask:栈内单例模式,当一个具有singleTask模式的Activity请求启动后,比如Activity A,系统会判断是否有A想要的任务栈,如果没有,重新创建一个任务栈,然后将A压入栈中;如果存在A需要的任务栈,这时需要看A是否在这个栈中,如果在把A调到栈顶(如果栈中Activity A之上有其他Activity ,在其之上的全部出栈),并会调用A的onNewIntent方法。如果不存在A的实例就把A压入栈中。
  4. singleInstance:单例模式。这是一种加强的singleTask模式,它除了具有singleTask模式的所有特性。且此模式Activity 只能单独的位于一个任务栈中。比如说Activity A是singleInstance模式,当A启动后,系统会为他创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求都不会创建新的Activity,除非这个任务栈被系统销毁。

IntentFilter 的匹配规则

启动Activity分为两种:显示调用、隐式调用

  • 显示调用:需要明确指定被启动Activity的组件信息,包括包名和类名
  • 隐式调用:需要Intent 能够匹配目标组件的IntentFilter中所设置的过滤信息,只有一个Intent同时匹配action、category、data类别才算完全匹配,只有完全匹配才能成功启动目标Activity。一个Activity可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应Activity

action的匹配规则

action的匹配规则是:Intent中的action必须和匹配规则中的action匹配,且必须和匹配规则中的其中一个action相同。action区分大小写。

category的匹配规则

category要求Intent可以没有category,但是如果你一旦有category,不管你有几个category,每一个都要能够和匹配规则中的任何一个category相同。或者不设置category,因为系统在调用startActivity 或startActivityForResult 是会默认为Intent加上 “android.intent.category.DEFAULT” 这个category。同时为了Activity能够隐式调用,就必须在intent-filter 中指定“android.intent.category.DEFAULT” 这个category

data的匹配规则

data的匹配规则和action的匹配规则类似,如果过滤规则中定义了data,那么Intent中也必须要定义相匹配的data

data语法,如下图
这里写图片描述

data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg 、audio/mpeg4-generic 、video/*等,可以表示图片、文本、视屏的不同的媒体格式,
URI 中包含的数据就比较多了,如下图
这里写图片描述

  • Scheme:URI的模式,比如http、file、content等,如果URI 中没有指定scheme,那么整个URI 的其他参数无效,URI 亦无效。
  • Host:URI 的主机名,比如www.baidu.com,如果host未指定,那么整个URI中的其他参数无效,URI 亦无效。
  • Port:URI 的端口号,比如80,仅当URI 指定了scheme 和 host 参数的时候port参数才有意义。
  • Path:表示完整的路劲信息。
  • pathPattern:也表示完整的路劲信息,但是它可以包含通配符 。
  • pathPrefix:表示路劲的前缀信息

检测是否有Activity 能够匹配我们的隐式Intent

  • 方法一:采用PackageManager的resolveActvity 方法
  • 方法二:采用Intent 的 resolveActvity 方法

猜你喜欢

转载自blog.csdn.net/qq_26057629/article/details/80908610