对于Activity你需要知道些什么?
目录:
- Activity的生命周期
- Activity的任务栈
- Activity的四种启动模式
- Activity的Flags
生命周期
下面就是老僧常谈的七大生命周期了:
1. onCreate (@Nullable Bundle savedInstanceState)
一个Activity生命的开始,在这个方法中,我们通常会做一些初始化的处理,比如:初始化布局 - - setContentView;绑定UI控件 - - findViewById等。眼大的同学可能看到(眼小也能QAQ)这里需要传入一Bundle,这个可是有大用处的,下面会具体说它,这里先不管它(①号坑)。
2.onStart
Activity正在启动,此时的Activity已经可见,但是并没有出现在前台,并无法与用户进行交互。我们可以理解为,此时Activity已经显示出来了,但是我们并看不到。它隐身了!隐身了你能信!
3.onResume
Activity由后台移至前台,并且开始活动。也就是破除隐身状态,让我们不仅可以看到它,还能操作它,点击,滑动,任你玩。
4.onPause
此时Activity正在停止,Activity由前台进入后台,也就是进入隐身状态,同时不可交互。正常情况下onStop会紧接着调用,期间时间很短。如果在这个方法中进行耗时操作会影响新Activity的显示(下面会解释这一原因)(②号坑)。
5.onStop
此时Activity即将停止,状态由可见转换为不可见,也就是由隐身转变为下线。我们一般在这个方法中进行一些稍微重量型的回收工作。
6.onDestory
Activity即将进入死亡状态,马上被回收掉,我们在这里进行重量型的回收工作。
7.onReStart
这个比较特殊,表示Activity正在重新启动。当当前Activity由不可见(隐身)状态进入可见(上线)状态的时候此生命周期才会执行。
来个完整的图解:
生命周期.jpg这个生命周期图比官方的生命周期图更加清晰。
- 第一层(onCreate)-(onDestroy)表示Activity的创建和销毁;
- 第二层(onStar)-(onStop)表示Activity已经启动,但是没有显示在前台,是可见状态,但是没有获取焦点,也就是不可交互状态(隐身状态);
- 第三层(onResume)-(onPause)表示Activity显示在前台,用户可见并且可以交互(上线状态)。
下面开始填坑了:
①号坑: onCreate (@Nullable Bundle savedInstanceState)
可以看到这里有一个Bundle savedInstanceState,那它是干嘛的呢?
正常情况下,我们是用不到这个值的;只有在异常状况下,我们才会用到它。
那什么是异常情况呢?
当系统的配置发生改变,或者系统在资源不足的情况下回收掉隐身的Activity。此时系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法是在onStop之前,但是它和onPause并没有既定关系,它既可能在onPause之前调用,也可能在onPause之后调用。当Activity重建后,系统会调用onRestoreInstanceState来还原之前保存的状态。
②号坑: Activity-A启动Activity-B,那么这两个Activity的生命周期是如何进行的?
如果想详细了解这个生命周期,那需要了解Activity的启动源码,无奈本人水平不够,没法解释,只能通过最简单的办法解决,新建两个Activity,覆写生命周期,打印log,简单除暴,通过log显示可以看出,只有第一个Activity的onPause执行之后第二个Activity的onCreate才会执行,这也就解释了为什么不能在onPause进行耗时操作。
任务栈
关于栈结构,相信大家都不陌生,后入先出的线性表。而在Android中就是通过任务栈管理多个Activity的。
默认情况下,当一个APP启动的时候,系统通常会为其创建一个任务栈,用于存放和管理这个APP启动的所有Activity。当一个Activity启动了另一个新的Activity的时候,新的Activity就会置于该任务栈的栈顶,并且处于活动状态,也就是(上线)状态。
启动模式
Android的Activity是四大组件之一,除了Activity的生命周期外,Activity的启动模式也是非常重要的。为了了解Activity的启动模式,首先我们要知道我们为什么要使用启动模式?启动模式存在的意义是什么?
我们知道,在默认情况下,当我们多次启动同一个Activity的时候,系统会创建多个实例,并把它们一一放入任务栈中,当我们点击back键时,会发现这些Activity会一一回退。知道了Activity的默认启动模式之后,我们就会发现一个问题:多次启动同一个Activity,系统会重复创建多个实例,这样很明显是不合理的,为了解决这个问题就要用到我们说的Activity的启动模式。目前安卓有四种启动模式:standard、singleTop、singleTask和singleInstance,想要更改模式可以在AndroidManifest.xml中activity标签下添加launchMode标签。下面是各种模式的详细介绍:
(一)standard:标准模式,这也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管实例是否已经存在。被创建的实例的生命周期符合典型的Activity的生命周期。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。比如ActivityA 启动了ActivityB(B也是standard模式),那么B就会进入到A所在的栈中。
《Android开发艺术探索》中介绍了:如果我们用ApplicationContext去启动standard模式的时候Activity的时候会报错,错误的原因是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,所有这就有问题了。解决这个问题的方法是为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈,这时候待启动Activity实际上是一singleTask模式启动的。
活动启动图:
Standard启动模式
上图可以看出来,我们每次启动一个A活动的时候,都会创建一个新的A活动放在当前栈的顶端。点击返回键会回到前一个A活动,直到退出程序。你们可以写一个小Demo自己测试亲自体验一下。
(二)singleTop:栈顶复用模式。在这种模式下,如果新Activity已经位于任务栈的栈顶(处于完全可见状态),那么此Activity不会被重新创建。但是如果新的Activity不是位于栈顶(处于不完全可见状态),那么新Activity仍然会重新创建。
在singleTop(栈顶复用模式)下,如果Activity位于栈顶,我们再次启动该方法,那么该方法会回调onNewIntent方法,而onCreate、onStart方法不会被调用。
活动启动图:
SingleTop启动模式
上图可以看出来,如果活动B位于栈顶时,我们再次启动活动B,则不会创建新的活动B,如果B不位于栈顶,则会创建新的活动B。
(三)singleTask:栈内复用模式。这是一种单实例模式,在这种模式下,一个Activity在一个栈中只能有一个实例,类似单例模式。详细讲解,当一个具有singleTask模式的Activity请求启动后,例如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个新的任务栈,然后创建A的实例后把A 放到栈中。如果存在A所需要的任务栈,再看Activity A 是否在栈中有实例存在,如果有实例存在,那么系统就会把A调到栈顶并调用onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中。
活动启动图:
SingleTask栈内复用模式
上图可以看出来,活动启动的顺序是A→B→C→D→B,第一次启动B的时候栈内没有实例,系统会创建新的B的实例,但第二次启动B的时候,系统查询任务栈,发现有实例,系统就会把活动B移到栈顶,并且把B之上的所有活动出栈。
(四)singleInstance:单实例模式。这是一种加强的singleTask模式,它除了具有singleTask模式所具有的所有特性外,还加强一点,那就是具有此种模式的Activity只能单独的位于一个任务栈中。简单而言,如果一个活动是singleInstance的启动模式,那么该活动就只能单独位于一个栈中。
活动启动图:
SingleInstance:单实例模式
图中看出,如果一个活动是singleInstance模式,那么活动C会单独创建一个新的任务栈,而返回栈中,活动C处于的任务栈会先压入返回栈的栈低,再把另外一个活动栈放入返回栈中。
通过Flags设置启动模式
Activity有很多Flags,我们主要分析启动模式相关的Flags。
- FLAG_ACTIVITY_NEW_TASK
使用一个新栈来启动Activity,跟在xml中设置android:launchMode=“singleInstance”效果相同。 - FLAG_ACTIVITY_SINGLE_TOP
使用SingleTop模式启动一个Activity,跟在xml中设置android:launchMode=“singleTop”效果相同 - FLAG_ACTIVITY_CLEAR_TOP
使用SingleTask模式启动一个Activity,跟在xml中设置android:launchMode=“singleTask”效果相同 - FLAG_ACTIVITY_NO_HISTORY
使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就会消失,不会存留与栈中。
总结:写了三晚上终于写完了,认真的写一篇博客真的好难。不过认真写博客确实能提高很多,需要认真分析问题,列出大纲,然后整理资料,书写文章。通过这篇博客,复习了Activity的相关知识,巩固了之前不足的地方,也发现了很多新的问题。以后会不断复习,不断写高质量的博客。在代码的路上奋斗下去!!!