Activity的生命周期和启动模式

来源:互联网 发布:淘宝店铺招牌是什么 编辑:程序博客网 时间:2024/06/16 19:31

Activity的生命周期:

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

onCreate():创建Activity的时候调用,此时可以做一些初始化界面的工作

onRestart():当A界面启动B界面,然后返回B界面会调用A界面的这个方法。重新启动界面

onStart():Activity从变为可见,但是还不能跟用户进行交互

onResume():Activity可见,并且与用户可交互

onPause():Activity暂停,界面失去焦点,但是界面依旧可见

onStop():Acitivity界面停止,界面不可见

onDestory():Activity被销毁说明:界面A启动界面B,会先调用界面A的onPause()方法,才会调用界面B的onResume()方法。

原因:在ActivityThread的scheduleLaunchActivity()方法中可以看出,最直接的办法就是写个demo证明,如下:


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

  在异常情况下,除了上述说的7个生命周期外,系统还会调用onSaveInstanceState()方法来保存当前Activity的状态,里面保存的数据类型为Bundle类型,当Activity被重新创建的时候,系统会调用onRestoreInstanceState()方法来恢复之前保存的数据。最常见的情况就是屏幕的旋转,如图所示:


上图的Log信息是屏幕有竖屏旋转到横屏时候的生命周期的变化,可以看到onSaveInstanceState()方法的调用是在onStop()之前,onRestoreInstanceState()的方法调用是在onResume()方法之前。另外需要注意的是,系统有两个onSaveInstanceState()方法可以继承,而这里状态的保存是在带一个参数的onSaveInstanceState()方法中执�%C的。如下图:


这里说到横竖屏的切换,通过实验,竖屏切换为横屏与横屏切换为竖屏的生命周期是一样的,网上很多说横屏切换为竖屏时,生命周期会执行两次,但是自己写的demo是一次。

当然,如果不希望横竖屏切换的时候Activity被销毁,那么可以在mainfest清单文件中设置configChanges:orientation;这时候横竖屏切换时,生命周期如下:


说明:上图log信息是竖屏切换横屏然后切到竖屏的信息,可以看到切换时生命周期不会再次调用,而是调用onConfigurationChanged()方法。

另外在清单文件中除了给configChanges属性设置orientation以外,还设置了screenSize,原因是我的minSdkVersion和targetSdkVersion有一个大于13。原因如下:

现在对configChanges常用的几个值介绍下:

local:设备的本地位置发生了变化一般指切换了系统语言

orientation:屏幕方向发生了变化

screenSize:当屏幕的尺寸信息发生了改变,当旋转设备屏幕时,屏幕尺寸发生变化,这个选项比较特殊,当编译选项中的minSdkVersion和targetSdkVersion均低于13时,此选项不会导致Activity重启,否则会导致Activity重启(API13新添加)

keyboardHidden:键盘的可访问性发生了改变,比如用户调出了键盘

当然还有一些其他值,这里列出常用的。通过上面解释,我想上面设置screenSize的原因也就说明了。

Activity的优先级:

前台Activity:正在和用户交互的Activity,优先级最高

可见非前台Activity:比如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和用户直接交互

后台Activity:已经被暂停的Activity,比如执行了onStop,优先级最低。

资源内存不足的时候会导致低优先级的Activity被杀死。

Activity的启动模式:

Activity的LaunchMode
standard:标准模式,默认模式。每次启动一个Activity时都会创建一个新的Activity实例压入栈中。
singleTop:如果被启动的Activity是此模式,当该Activity已经处在栈顶,那么就不会再创建新的实例,同时它的onNewIntent方法会被回调,通过此方法的参数我们可以获取当前请求的信息,另外onCreate()和onStart()方法不会被调用。
singleTask:单例模式,当被启动的Activity已经存在栈中,那么在该Activity之上的Activity实例都会被弹出栈,同时它的onNewIntent方法会被回调
singleInstance:当Activity设置为此模式时,系统会为其新建一个栈,并且这个栈里面只会有该Activity一个实例存在
有种情况说明:当后台任务栈为:DC,前台任务栈为:BA,并且DC的启动模式均为singleTask,如果是启动D,那么栈中的情况为:DCBA,如果是启动C,那么情况会是:CBA。
标识Activity任务栈的属性为:TaskAffinity,在清单文件中可以为此属性设置值,那么该Activity就会在其设置的TaskAffinity值对应的栈中。默认情况下,所以Activity所需的任务栈的名字都是应用的包名。TaskAffinity主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。
当TaskAffinity与singleTask配合使用时,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中。
当TaskAffinity与allowTaskReparenting配合使用时。常用之处:当A应用启动B应用的Activity C,如果Activity C的allowTaskReparenting的值为:true.那么当Activity C被A应用启动,按home键,再点击B应用图标,此时出现的界面会是Activity C。本应该在A应用栈中的C就会转移到B应用的任务栈中。

Acitivity指定启动模式的两种方式:在清单文件中设置LaunchMode的值,另一种是在Intent中设置标志位。
区别:第二种方式的优先级高于第一种方式;两种方式在限定范围内有不同,第一种无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识,第二种方式无法为Activity指定singleInstance模式。
介绍Activity的几个主要flags:
  FLAG_ACTIVITY_NEW_TASK<=>singleTask
  FLAG_ACTIVITY_SINGLE_TOP<=>singleTop
  FLAG_ACTIVITY_CLEAR_TOP:此标记常与singleTask启动模式一起出现,这种情况下,被启动的Activity的实例如果已经存在,那么系统会调用它的onNewIntent。如果被启动的Activity是standard模式启动,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶。
 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有此标记的Activity不会出现在历史Activity的列表中,同在XML中设置excludeFromRecents="true"效果相同。

IntentFilter的匹配原则

隐式调用调用需要Intent能够匹配目标组件所设置的IntentFilter过滤信息。过滤信息有:action,category,data.过滤信息可以有多个,只要Intent能匹配任意一组就行。
匹配原则:
action:Intent中存在且必须和过滤规则中的其中一个action相同。区分大小写。
category:Intent中可以不指定category,这个时候系统会自动为Intent加上“android.intent.category.DEFAULT”这个category,为了能够接受隐式调用,那么过滤信息中也要设置这个category.
data:由mimeType和URI组成。mimeType指媒体类型,URI必须包括:Scheme和Host,否则无效。data的匹配规则和action类似,如果只指定了mimeType,没有指定URI,那么默认的URI值为content和file,所以Intent中URI部分的schema必须为file或者content才能匹配。
注意:为Intent指定完整的data,必须调用setDataAndType()方法,调用setData再调用setType,后者会清除后者的值。
最后通过隐式方式启动Activity时,可以做一下判断。方法有二:采用PackageManager的resolveActivity方法或者采用Intent的resolveActivity方法,如果找不到匹配的Activity就会返回Null。




0 0