思考:
看到这个题目相信很多人有这种感觉,太简单了,如果让他描述每个生命周期名字作用,启动过程,从第一个页面跳到第二个页面生命周期的过程。不一定说的清楚,所以记录下来加深一下印象。
1.activity的生命周期
先贴一张官方文档(http://developer.android.com/reference/android/app/Activity.html)的图。
相信这张图你百分百看过,我来简略的介绍一下Activity的生命周期:
上面图片截的不好看,有好的滚动截图工具可以推荐一下。
1. 给每个生命周期写上日志,启动app,可以看到启动一个activity的生命周期,如下图:
2.同样你再新建一个页面,从第一个页面跳转到第二个页面到生命周期,如下图:大家可以看到,跳转时,第一个页面先onPause,当前看到的还是第一页面,等到第二个页面启动成功了,才看到第二页面,并停止第一页面。
3.还有一个自调用的方法onSaveInstanceState:
当我们的app长时间切到后台,或者一些不在栈顶的页面,当我们重新进入的时候,这个Activity或者Fragment就会被重新onCreate,但是此时,页面中具有id的控件,这些值都是会被系统自动保存下来的。这是因为onSaveInstanceState()这个方法起了作用。
4.横竖屏切换的时候,生命周期方法的回调顺序为:
onPause--onSaveInstanceState--onStop--onDestory--onCreate--onStart--onResume
也就是说Activity被销毁并重建了。当然你也可以在清单文件中对应的Activity添加一行配置:
android:configChanges="keyboardHidden|orientation|screenSize"
2.activity的启动模式
什么是Task
Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的 Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多 Activity,Task结束。
task是一系列activity的集合, 这些activity通常因为同一目的而启动, 系统将这些activity按照创建的顺序组织在栈中(也就是所谓的back stack). 每一个task都拥有一个仅属于它的back stack.
管理任务和回退栈
1.通过Activity的启动模式去控制:Activity的 launchMode
standard: (备注:standard是系统默认的启动模式。)
标准启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
如果启动此Activity的Intent中没有设置FLAG_ACTIVITY_NEW_TASK标志, 则这个Activity与启动他的Activity在同一个Task中,如果设置了Activity请参考上面FLAG_ACTIVITY_NEW_TASK的详细说明,"launchMode"设置为"standard"的Activity可以 被实例化多次, 可以在Task中的任何位置, 对于一个新的Intent请求就会实例化一次.
singleTop:
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,而不会创建新的Activity对象,不过它会调用 onNewIntent()方法。如果栈顶部不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
如果启动此Activity的Intent中没有设置FLAG_ACTIVITY_NEW_TASK标志, 则这个Activity与启动他的Activity在同一个Task中,如果设置了Activity请参考上面FLAG_ACTIVITY_NEW_TASK的详细说明,"launchMode"设置为"singleTop"的Activity 可以被实例化多次, 可以在Task中的任何位置, 对于一个新的Intent请求如果在Task 栈顶, 则会用栈顶的Activity响影Intent请求,而 不会重新实例化对象接收请求, 如果 没有在栈顶, 则会 实例化一个新的对象接收Intent请求.
singleTask:
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
和singleTop在名字上即可看出区别,即singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而singleTask则会检测栈中全部的Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检测到的我们需要的Activity置为栈顶。
"launchMode"设置为"singleTask"的Activity 总是在栈底, 只能被 实例化一次, 它允许其它Activity压入"singleTask"的Activity所在的Task栈,如果有新的Intent请求有此标志的Activity, 则系统会清除有此标志的Task栈中的全部Activity,并把此Activity显示出来.
singleInstance:
在一个 新栈中创建该Activity实例,并让多个应用共享该Activity实例。一旦这种模式的Activity实例存在于某个栈中,任何应用再激活这个Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。此启动模式和我们使用的浏览器工作原理类似,在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。
"launchMode"设置为"singleInstance"的Activity总是在栈底, 只能被实例化一次, 不允许其它的Activity压入"singleInstance"的Activity所在Task栈, 即 整个Task栈中只能有这么一个Activity.
设置启动模式的位置在 AndroidManifest.xml 文件中 Activity 元素的 android:launchMode 属性
2.动态的启动模式:在new 一个Intent后,通过Intent的addFlags方法去动态指定一个启动模式
Intent intent = new Intent();intent.setClass(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
以下介绍几个基本的标记位,不用背,须要时再查官方文档:
1. FLAG_ACTIVITY_NEW_TASK
作用是为Activity指定 “SingleTask”启动模式。跟在AndroidMainfest.xml指定效果同样。
2. FLAG_ACTIVITY_SINGLE_TOP
作用是为Activity指定 “SingleTop”启动模式,跟在AndroidMainfest.xml指定效果同样。
3. FLAG_ACTIVITY_CLEAN_TOP
具有此标记位的Activity,启动时会将与该Activity在同一任务栈的其他Activity出栈。一般与SingleTask启动模式一起出现。它会完毕SingleTask的作用。但事实上SingleTask启动模式默认具有此标记位的作用
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记位的Activity不会出如今历史Activity的列表中,使用场景:当某些情况下我们不希望用户通过历史列表回到Activity时,此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:
结束语:
关于Activity 的生命周期和启动模式,有很多值得我们不断研究的知识,我仅仅只是抛砖引玉。大家一定要自己动手去尝试。
GitHub:https://github.com/DaveSally/MyDemo
欢迎大家关注我的公众号:受伤的粽子