Android学习笔记之Activity的生命周期和启动模式
每次看看新的旧的知识,总有意想不到的收获,这次的学习笔记会是一个漫长的系列,在学习中总结出来的东西,影响更加深刻,所以我也开始了博客之旅。
这个系列的第一篇为Activity的生命周期和启动模式。
---------------------------------------分割线---------------------------------------
一、Activity生命周期
总结:activity的生命周期,分为两种情况,正常情况和异常情况。
1、正常情况,就是那几个生命周期的函数的调用,正常顺序如下:onCreate->onStart->onResume->onPause->onStop->onDestory,其次还有当activity存在后,从不可见到可见会调用onRestart->onStart->onResume。
注意:
(1)启动另一个activity,会先调用当前activity的onPause方法后才会去调用启动的activity的生命周期,如上。
(2)如果打开新的Activity或切换到桌面,打开新的activity时,新activity的背景采用透明,则当前不会调用onStop方法。
2、异常情况,在异常情况下,activity将会被杀死,也可以分为两种情况:资源相关的系统配置发生改变,资源内存不足。两种情况下都会回调onSaveInstanceState来保存当前activity的一些状态,然后重新创建时在onCreate和onRestoreInstanceState来恢复数据,官方建议恢复数据时使用onRestoreInstanceState。保存和恢复的过程是利用委托机制,就以保存为例,先是activity委托Window去保存数据,Window委托其内部顶层容器ViewGroup即DecorView去保存数据,然后顶层容器再一一去通知子View来保存数据。其中系统提供的View已经为我们实现了部分数据的保存与恢复,具体细节查看源码,也是通过onSaveInstanceState和onRestoreInstanceState保存和恢复数据。
注意:
(1)onSaveInstanceState的调用,需要在activity即将被销毁并有机会重新显示时才会去调用,所以正常情况下的关闭则不会调用该方法;例如,A启动B时,A的该方法也会被调用,但是当B关闭后A的onRestoreInstance只有当A被回收后才会被调用。
(2)资源不足时销毁的机制,会根据activity的优先级去销毁,越低越容易被销毁,activity的优先级从高到低如下三种:a.前台activity,与用户交互;b.可见但非前台,如activity中弹出了dialog;c.后台activity,不可见。不单单是activity,其他系统之源也是一样,所以后台任务放在Service中,保证一定的优先级,这样才不会轻易被系统回收。
(3)禁止系统配置发生改变。通过配置文件中的android:configChanges属性来确保哪些系统配置改变时不会重建activity,常用的属性有local,keyboardHidden,orientation,screenSize和smallestScreenSize,后两者若是编译的sdk版本在13以上时,例如在设置orientation时还需要加上screenSize,其具体含义自行google。
二、Activity启动模式
总结:activity的启动模式有四种:standard、singleTop、singleTask和singleInstance,启动模式的指定有两种方式AndroidMenifest或者设置Intent的标志位来制定;首先得知道一个概念,任务栈,用于存储这些activity的索引,也是后进先出的结构。
1、系统默认的启动模式为standard,该模式下,谁启动则在谁的任务栈中,则以非activity类型的context启动新的activity时,需要设置一个标志位(FLAG_ACTIVITY_NEW_TASK),因为此时启动他的context中没有任务栈。
2、singleTop,只有当要启动的activity在栈顶且存在时,该activity才会被重用,重用时会回调onNewIntent方法,其他的回调方法和正常生命周期一样。
3、singleTask,只要activity存在,则就会复用,复用时,会将栈内在他之上的activity出栈,重用时会回调onNewIntent方法,其他的回调方法和正常生命周期一样。
4、singleInstance,是一种加强版的singleTask,singleInstance的activity会单独占用一个任务栈,而singleTask可以指定一个任务栈,栈名通过taskAffinity属性去设置,其值为字符串,但必须要包含包名分割符”.”。
5、标志位:常用的有FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS。具体什么意思自行google。
6、IntentFilter的匹配,包括action,category和data,action和data匹配方式只要有,就都得为Intent设置上,但是只需有一个action和一个data匹配上即可,而category在配置文件中必须设置上android.intent.category.DEFAULT,否则匹配不成功,是否能匹配成功,可以通过PackageManager的resolveActivity或queryIntentActivities来判断,前者判断方式为是否为null,后者为是否为null或者是否size==0。
注意:
(1)action的匹配只需要匹配到某个filter下的某个action即可,值为字符串区分大小写。
(2)category的匹配,intent中设置的category都需要在配置中找得到,且可以不设值。
(3)data的匹配和action只需要匹配到某个filter下的某个data即可,其属性比较复杂,data是由mimeType和Uri组成的,mimeType是媒体类型,Uri的结构如:
具体含义请自行google,具体结构例如:
content://com.example.project:200/folder/subfolder/etc
http://www.baidu.com:80/search/info
---------------------------------------分割线---------------------------------------
写到这里就基本上写完了,希望看到的朋友,若发现有问题的地方请多多指教。