Android开发艺术探索1

Android开发艺术探索1

该系列文章为《Android开发艺术探索》读书笔记,仅作为学记录,勿喷。

Activity的生命周期

  1. onCreate表示Activity正在被创建,可以做一些初始化工作 eg:setContentView
  2. onRestart表示Activity正在重启。一般当前Activity不可见会调用onRestart。按下home->onPause->onStop->重新进入onRestart
  3. onStart表示Activity正在被启动,Activity可见,还没有出现在前台,无法和用户交互。可理解为Activity显示了,但我们看不到
  4. onResume表示Activity已经可见了,出现在前台并开始活动
  5. onPause表示Activity正在停止。正常情况之后调用onStop,特殊情况如果快速返回当前Activity,onResume会调用。这里可以做一些存储数据,停止动画等工作,但不能太耗时,会影响新Activity的显示。
  6. onStop表示Activity即将停止。可以做稍微重量级的回收操作,也不能太耗时
  7. onDestroy表示Activity即将被销毁,可以做一些回收工作和最终的资源释放

Activity在异常终止的情况下会调用onSaveInstanceState来保存当前的Activity状态,调用时机在onStop之前,和onPause没有既定的时序关系,可能在之前也可能在之后。

onRestoreInstanceState的调用时机在onStart之后。

  • onRestoreInstanceState 和 onCreate的区别:onRestoreInstanceState一旦被调用其参数Bundle saveInstanceState一定有值,不用额外判断是否为空;但onCreate正常启动参数为null,需要判断。官方建议采用前者恢复数据。

Activity的启动模式

  1. standard标准模式,系统默认模式,谁启动这个Activity,那么这个Activity就运行在启动它的Activity所在栈中。从非Activity类型的Context(例如ApplicationContext、Service等)中以standard模式启动新的Activity是不行的,因为这类context并没有任务栈,所以需要为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标志位。
  2. singleTop栈顶复用模式,新Activity已经位于任务栈的栈顶,那么此Activity不会重新创建,同时它的onNewintent方法被回调。
  3. singleTask栈内复用模式。这是一种单实例模式。当一个具有singleTask启动模式的Activity请求启动之后,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建Activity的实例把它放到栈中;如果存在Activity所需的任务栈,这时候要看栈中是否有Activity实例存在,如果有,那么系统就会把该Activity实例调到栈顶,并调用它的onNewIntent方法(它之上的Activity会被迫出栈,所以singleTask模式具有FLAG_ACTIVITY_CLEAR_TOP效果);如果Activity实例不存在,那么就创建Activity实例并把它压入栈中。
  4. singleInstance单实例模式,此种模式的Activity只能单独的处于一个任务栈中,由于栈内复用的特性,后续都不会创建新的Activity,除非这个单独的任务栈被销毁了

    • 任务栈分为前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态,用户可以通过切换将后台任务栈再次调到前台
    • 设置启动模式既可以使用xml属性android:launchMode,也可以使用代码intent.addFlags()。区别在于限定范围不同,前者无法直接为Activity设置FLAG_ACTIVITY_CLEAR_TOP标识,而后者无法为Activity指定singleInstance模式。

TaskAffinity:任务相关性,标识一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名。可以为每个Activity单独制定TaskAffinity,值必须不能和包名相同,否则相当于没有指定。TaskAffinity主要和singleTask或者allowTaskReparenting配对使用。

当TaskAffinity和singleTask启动模式配对使用的时候,它是具有该模式的Activity的目前任务栈的名字,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中

当TaskAffinity和allowTaskReparenting结合的时候,当一个应用A启动了应用B的某个Activity C后,如果Activity C的allowTaskReparenting属性设置为true的话,那么当应用B被启动后,系统会发现Activity C所需的任务栈存在了,就将Activity C从A的任务栈中转移到B的任务栈中。

TaskAffinity属性值为字符串,且中间必须含有包含分隔符“.”

Activity的Flags

  • FLAG_ACTIVITY_NEW_TASK,FLAG_ACTIVITY_SINGLE_TOP,FLAG_ACTIVITY_CLEAR_TOP
    FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有这个标记的Activity不会出现在历史Activity列表中,当某些情况下我们不希望用户通过历史列表回到我们的Activity的时候这个标记比较有用,它等同于属性设置android:excludeFromRecents=”true”。

IntentFilter的匹配规则

1 列表内容
IntentFilter中的过滤信息有action、category、data,为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败。一个过滤列表中的action、category、data可以有多个,所有的action、category、data分别构成不同类别,同一类别的信息共同约束当前类别的匹配过程。只有一个Intent同时匹配action类别、category类别和data类别才算完全匹配,只有完全匹配才能成功启动目标Activity。此外,一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intenf-filter即可成功启动对应的Activity。

    <intent-filter>
        <action android:name="com.ryg.charpter_1.c" />
        <action android:name="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>

2 action匹配规则:只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功,action匹配区分大小写
3 category匹配规则:Intent中如果有category那么所有的category都必须和过滤规则中的其中一个category相同,如果没有category的话那么就是默认的category,即android.intent.category.DEFAULT,所以为了Activity能够接收隐式调用,配置多个category的时候必须加上默认的category。
4 data匹配规则:data的结构很复杂,语法大致如下

<data android:scheme="string"
            android:host="string"
            android:port="string"
            android:path="string"
            android:pathPattern="string"
            android:pathPrefix="string"
            android:mimeType="string" />

主要由mimeType和URI组成,其中mimeType代表媒体类型,而URI的结构也复杂,大致如下:

 <scheme>://<host>:<port>/[<path>]|[<pathPrefix>]|[pathPattern]

例如

content://com.example.project:200/folder/subfolder/etc

scheme、host、port分别表示URI的模式、主机名和端口号,其中如果scheme或者host未指定那么URI就无效。
path、pathPattern、pathPrefix都是表示路径信息,其中path表示完整的路径信息,pathPrefix表示路径的前缀信息;pathPattern表示完整的路径,但是它里面包含了通配符(*)。

data匹配规则:Intent中必须含有data数据,并且data数据能够完全匹配过滤规则中的某一个data。
URI有默认的scheme!
如果过滤规则中的mimeType指定为image/或者text/等这种类型的话,那么即使过滤规则中没有指定URI,URI有默认的scheme是content和file!如果过滤规则中指定了scheme的话那就不是默认的scheme了。

    //URI有默认值
    <intent-filter>
        <data android:mimeType="image/*"/>
        ...
    </intent-filter>
    //URI默认值被覆盖
    <intent-filter>
        <data android:mimeType="image/*" android:scheme="http" .../>
        ...
    </intent-filter>

如果要为Intent指定完整的data,必须要调用setDataAndType方法!
不能先调用setData然后调用setType,因为这两个方法会彼此清除对方的值。

intent.setDataAndType(Uri.parse(“file://abc”), “image/png”);

data的下面两种写法作用是一样的:

    <intent-filter>
        <data android:scheme="file" android:host="www.github.com"/>
    </intent-filter>

    <intent-filter>
        <data android:scheme="file"/>
        <data android:host="www.github.com"/>
    </intent-filter>

如何判断是否有Activity能够匹配我们的隐式Intent?

(1)PackageManager的resolveActivity方法或者Intent的resolveActivity方法:如果找不到就会返回null
(2)PackageManager的queryIntentActivities方法:它返回所有成功匹配的Activity信息
针对Service和BroadcastReceiver等组件,PackageManager同样提供了类似的方法去获取成功匹配的组件信息,例如queryIntentServices、queryBroadcastReceivers等方法

public abstract List queryIntentActivities(Intent intent,int flags);
public abstract List ResolveInfo(Intent intent,int flags);

上面两个方法第一个参数好理解,第二个参数需要注意,我们要使用MATCH_DEFAULT_ONLY这个标记位,含义是仅仅匹配那些在intent-filter中声明了

    <category android:name="android.intent.category.Default"/>

这个category的Activity。这标记的意义在于,只要上述的两个方法不返回null,那么startActivity一定可以成功。如果不用这个标记位就可以把intent-filter中category不含DEFAULT的那些Activity给匹配出来,导致startActivity可能失败。因为不含有DEFAULT这个category的Activity无法接收隐式Intent的。

有一类action和category比较重要,它们在一起用来标明这是一个入口Activity,并且会出现在系统的应用列表中

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值