Activity的生命周期与启动模式

来源:互联网 发布:ubuntu拷贝文件 改名 编辑:程序博客网 时间:2024/06/05 05:43

Activity的生命周期与启动模式

1 Activity的生命周期

1.1 典型情况下的生命周期

(1) onCreate:该方法表示Activity正在被创建。在该方法中可以做初始化工作,如setContentVeiw,初始化Activity数据等。

(2)onStart:该方法执行表示Activity已经被创建且已经可见,但并没有出现在前台,不能与用户交互。

(3)onResume:该方法会在onStart方法执行后立即执行,将Activity转入前台,并开始活动。

(4)onPause:该方法一般在用户切换Activity时执行,当用户切换到一个新的Acitivity时,该方法立即被调用。在该方法内部可以做一些存储数据的工作,但会影响新Activity的显示,所以,应避免执行耗时操作。

(5)onStop:该方法会在onPause方法执行后立即执行,可以进行存储数据、资源回收等工作,不过应避免进行耗时操作。

(6)onRestart:该方法表示Activity正在重新启动,一般当前Activity从不可见重新变为可见时会调用该方法(如Home键返回桌面再次进入,打开新Activity后按back键返回等)。

(7)onDestroy:该方法表示Activity被最终销毁,在这里可以进行回收资源与数据保存等相关的操作。

经典的Activity生命周期图:

这里写图片描述

问题1:onStart和onResume有什么区别呢?

答:

(1)回调onStart方法后的Activity可见,但是未出现在前台,不可与用户交互。

(2)回调onResume方法后的Activity可见,并且出现在前台,可与用户进行交互。

问题2:onPause和onStop有什么区别呢?

答:

(1)回调onPause方法后的Activity处于Paused状态。Paused状态下的Acitivity是部分可见的。

(2)回调onStop方法后的Activity处于Stopped状态。Stopped状态下的Acitivity是不可见的。

问题3:切换Activity时两个Activity的生命周期方法执行的顺序?(从AActivity切换到BActivity)

答:

(1)新建Activity时:A.onPause->B.onCreate->B.onStart->B.onResume->A.onStop。

(2)back键返回时:A.onPause->B.onRestart->B.onStart->B.onResume->A.onStop。

1.2 异常状况下的生命周期

1.2.1 配置修改导致的Activity被杀死重建

在系统配置发生改变后,Activity会被销毁:onPause->onStop->onDestroy。

在这一过程中,系统在onStop方法调用之前调用onSaveInstanceState来保存当前Activity的Bundle对象(可能在onPause之前,也可能在onPause之后)。

在 Activity被重建过程中,Activity会取数据重建:onCreate->onStart->onResume。

在Activity被创建之后,系统会并在onStart方法之后调用onRestoreInstanceState方法取出由onSaveInstanceState方法保存的Bundle对象,恢复Activity的数据。

系统只在Activity被异常终止并且会马上重建时才调用onSaveInstanceState和onRestoreInstanceState方法存储和恢复数据,其他时候不会触发该过程。

1.2.2 资源不足导致低优先级Activity被杀死

优先级:前台Activity > 可见但非前台Activity > 后台Activity

低优先级的Activity被系统杀死后,如果被调入前台,那么将会重新执行该Activity的创建过程,但是其数据不会被自动保存与恢复,如果需要保存与恢复数据,需要在Activity的生命周期方法onSaveInstanceState 方法中添加数据保存操作,然后在 onCreate 方法中恢复数据。

2. Activity的启动模式

2.1 Activity的LaunchMode

Activity的Task具有“后进先出”的特点,Activity有四种启动模式:standard、singleTop、singleTask、singleInstance。

(1)standard:标准模式,即只要启动Activity就创建一个实例,并执行典型的生命周期:onCreate->onStart->onResume。

(2)singleTop:栈顶复用,当Activity在栈顶时不会创建新实例,不会调用onCreate、onStart方法,会回调onNewIntent方法,可以从onNewIntent方法的参数去除当前请求的信息。

(3)singleTask:栈内复用,只要Activity在一个栈内存在,那么会将栈内所有在该Activity之上的Activity全部出栈,使该Activity处于栈顶,而不会新建Activity,同时和singleTop一样回调onNewIntent方法。

(4)singleInstance:单例模式,具有该启动模式的Acitvity在启动时系统会为其单独创建一个Task栈,然后该Activity独自在该新Task栈中,在该栈被系统销毁前,任何请求都不会创建新的Activity,而只会栈内复用该Activity。

启动模式的设置有两种方法:

(1)在AndroidManifest文件中,Activity节点下,设置launchMode属性。

(2)在Intent中设置标志位为Activity指定启动模式,调用intent.addFlags()方法。

两种方式的不同点:

第二种方式优先级高于第一种,当两种方式都存在时,以第二种方式为准。

第一种方式无法为Activity设置FLAG_ACTIVITY_CLEAR_TOP标识。

第二种方式无法为Activity指定singleInstance模式。

练习题

AActivity的launchMode为Standard,BActivity的launchMode为SingleTask,CActivity的launchMode为SingleTask。B与C的taskAffinity属性相同,与A不同。现做如下操作:启动A->启动B->启动C->启动A->启动B,然后点击两次返回键,则出现哪个Activity?

答:回到桌面。流程如下:

(1)启动A,生成Task1,A入Task1栈。

(2)启动B,生成Task2,B入Task2栈。

(3)启动C,C入Task2栈。Task1栈:A,Task2栈:BC。

(4)启动A,A入Task2栈。Task1栈为A,Task2栈:BCA。

(5)启动B,Task2栈中CA被出栈,B到Task2栈顶。

(6)第一次返回键,B出栈,Task2栈被回收。Task1栈转入前台,A显现。

(7)第二次返回键,A出栈,Task1栈被回收,应用终止,回到桌面。

2.2 IntentFilter的匹配规则

    Activity的启动有两种方法:显式调用和隐式调用。显式调用需要明确被启动对象的组件信息,包括包名和类名。隐式调用不需要明确指定组件信息。若某个intent即为显示调用又为隐式调用,则以显式调用为主。

IntentFilter 的过滤信息有:action、category、data三种。

(1)action的匹配规则

action为一个字符串,系统预定义了一些action,同时也支持自定义action。匹配action时需要Intent的action和intentFilter中的action至少有一条字符串值完全一样。action区分大小写。

(2)category的匹配规则

category是个字符串,系统预定义了一些category,同时也支持自定义category。匹配category时需要Intent的category为intentFilter中的category的子集(即所有在intent中出现的category必须在intentFilter中出现过)。系统默认为Intent添加“android.intent.category.DEFAULT”这个category,因此若希望某activity能够被隐式调用,则必须在该Activity的intent-filter中添加 “android.intent.category.DEFAULT ” 这个category。

(3)data的匹配规则

和action的匹配规则相同。有几个需要注意的地方:

1、若在intent-filter中没有给出data的URI,则URI的默认值为content和file。

2、若要为Intent指定完整的data,必须调用setDataAndType方法,不可以分别调用setData和setType方法,因为这两个方法会互相清楚对方的值。
如下为setData方法源码:

 public Intent setData(Uri data){      mData = data;      mType = null;      return this; }

示例:

  <intent-filter>      <action android:name="com.ryg.charpter_1.c"/>      <action android:mame="com.ryg.charpter_1.d"/>      <category android:name="com.ryg.category.c"/>      <category android:name="com.ryg.category.d"/>      <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="text/plain"/>  </intent-filter>

该Intent-filter的完全匹配intent为:

 Intent intent = new Intent("com.ryg.charpter_1.c"); intent.addCategory("com.ryg.category.c"); intent.setDataAndType(Uri.parse("file://abc"),"text/plain"); startActivity(intent);

注:通过隐式方式启动一个Activity时,可以调用PackageManager的resolveActivity方法或者Intent的resolveActivity方法判断是否能够寻找到适配的Activity,如果不能寻找到,就会返回null。

原创粉丝点击