1. Activity的生命周期和启动模式《Android开发艺

2018-06-22  本文已影响0人  tesla1984

1.1 Activity的生命周期全面分析

  1. 典型情况下生命周期

    • onPause先执行完,新Activity的onResume才会执行
    • 当用户打开新Activity或者切换到桌面的时候,onPause->onStop。有一种特殊情况,如果新Activity采用透明主题,那么当前Activity不会回调onStop
    • onStart和onStop是从Activity是否可见这个角度来回调的
    • onResume和onPause是从Activity是否位于前台这个角度来回调的
  2. 异常情况下生命周期

    • 资源相关的系统配置发生变化导致Activity被杀死并重新创建(如横屏)
      • 当系统配置发生改变后,Activity会被销毁,onPause,onStop,onDestroy都会调用
      • Activity异常终止,系统会调用onSaveInstanceState来保存当前Activity的状态,这个方法的调用在onStop之前,和onpause没有既定的时间关系,可能在onPause之前,也可能在onPause之后
    • 资源内存不足导致低优先级Activity被杀死(数据存储和恢复过程和上面一致)

1.2 Activity的启动模式

  1. Activity的LaunchMode
    • standard
      ApplicationContext启动standard模式Activity会报错,因为standard模式的Activity默认会进入启动它的Activity所属的任务栈,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,解决这个问题的方法就是为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候启动Activity实际上是以singleTask模式启动的
    • singleTask
      当一个具有singleTssk模式的Activity请求启动后,比如Activity A,系统首先会寻找是否存在A想要的任务栈,
      如果不存在,就重新创建一个任务栈,然后创建A的实例后把A放到栈中。如果存在A所需要的任务栈,
      这时要看A是否在栈中有实例存在,如果有实例存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中
      singleTask默认具有clearTop的效果
    • singleInstance
      具有此种模式的Activity只能单独位于一个任务栈中。由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁
    • 任务栈
      • TaskAffinity该参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用包名。
      • TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,其他情况下没意义
      • 任务栈氛围前台任务栈和后台任务栈
      • 当TaskAffinity和allowTaskReparenting结合使用的时候,比如现在有2个应用A和B,A启动了B的一个Activity C,然后按Home键回到桌面,然后再单击B的桌面图标,这个时候并不是启动了B的主Activity,而是重新显示了已经被应用A启动的Activity C,或者说,C从A的任务栈转移到了B的任务栈中。可以这么理解,由于A启动了C,这个时候C只能运行在A的任务栈中,但是C属于B应用,正常情况下,它的TaskAffinity值肯定不可能和A的任务栈相同(因为包名不同)。所以,当B被启动后,B会创建自己的任务栈,这个时候系统发现C原本所想要的任务栈已经被创建了,所以就把C从A的任务栈中转移过来了。
      • 通过Manifest指定启动模式无法直接为Actiivty设定FLAG_ACTIVITY_CLEAR_TOP标识
      • 通过Intent指定启动模式无法为Activity指定singleInstance模式

1.3 IntentFilter的匹配规则

  1. action的匹配规则
    action的匹配要求Intent中的action存在且必须和过滤规则中的其中一个action相同。action区分大小写
  2. category的匹配规则
    • category要求Intent可以没有category,但是如果一旦有category,不管有几个,每个都要能够和过滤规则中的任何一个category相同。
    • 为什么不设置category也可以匹配?因为系统在调用startActivity或者startActivityForResult会默认为Intent加上“android.intent. category.DEFAULT”这个category,所以这个category就可以匹配前面的过滤规则中的第三个category。同时,为了我们的activity能够接收隐式调用,就必须在intent-filter中指定“android.intent.category.DEFAULT”这个category,原因刚才已经说明了。
  3. data的匹配规则
    • data的语法如下所示。
      <data android:scheme="string"
           android:host="string"
           android:port="string"
           android:path="string"
           android:pathPattern="string"
           android:pathPrefix="string"
           android:mimeType="string" />
    
    • data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg、 audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI中包含的数据就比较多了,下面是URI的结构:<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
    • 匹配规则
      <intent-filter>
           <data android:mimeType="image/*" />
           ...
        </intent-filter>
    
    这种规则指定了媒体类型为所有类型的图片,那么Intent中的mimeType属性必须为“image/*”才能匹配,这种情况下虽然过滤规则没有指定URI,但是却有默认值,URI的默认值为content和file。也就是说,虽然没有指定URI,但是Intent中的URI部分的schema必须为content或者file才能匹配,这点是需要尤其注意的。为了匹配(1)中规则,我们可以写出如下示例:intent.setDataAndType(Uri.parse("file://abc"),"image/png")。
    另外,如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法彼此会清除对方的值,这个看源码就很容易理解,比如setData:
    public Intent setData(Uri data) {
        mData = data;
        mType = null;
        return this;
    }
    
    可以发现,setData会把mimeType置为null,同理setType也会把URI置为null。
上一篇 下一篇

猜你喜欢

热点阅读