Intent解析

首先Intent为什么会存在,它的作用是什么?
我们知道Android四大组件Activity,Service,Broadcast Receive,Content Provider中有三个和Intent有明显的关系。Intent 的存在和Android系统密不可分,系统要了解手机上的每个应用,我们应用的每个Activity,Service,Content Provider都必须注册AndroidManifest文件中,Broadcast Receive没有强制要求,但在使用前也必须注册到系统中才能使用。我们知道这些组件的创建是由系统负责的,通过Intent我们可以告诉系统我们要如何启动对应的组件,各个组件是相互独立的,通过Intent我们可以在组件间传递数据。

Intent存在的作用:
1.告诉系统我们要查找的组件
2.告诉系统如何启动对应的组件
3.把数据传递给创建组件的实例

Intent的作用进行说明:
Intent中最重要的6个字段Component、Action、Data、Category、Flags、Extras。

一、查找组件
上面的6个字段Component、Action、Data、Category是用来和查找相关的,其中Data我更倾销于理解成URL。
查找之前我们先看我们在组件注册时(AndroidManifest文件或动态注册)给了哪些信息。

<activity.....
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="http" android:host="mei.youzan.com" android:port="80" android:path="/api" />
    </intent-filter>
</activity>

可以看到在注册时我们给的信息是一组IntentFilter,通常我们只会配置一个IntentFilter,IntentFilter包含3类数据 Action,Category,Data,每类数据同样可以注册多个。

显式Intent:Component字段的信息并没有在注册的配置信息中,他是通关过唯一的包名和类名来确定启动哪个组件,通常也只有我们自己应用内的组件调用会使用这种方式。
隐式Intent:通过设置的Action,Category,Data系统会帮我们找到对应的组件,下面是具体的匹配规则,一个组件在注册配置信息的时候可包含多个IntentFilter,只要我们的Intent设置Action,Category,Data和其中一个匹配就可可以。
单个IntentFilter的匹配规则:
注册配置信息

Intent匹配规则

Action的匹配
Manifest可配置多个Action,Intent只能配置一个Action,只要Intent中的Action在配置的Action中存在就匹配
Category的匹配
Manifest中可配置多个Category,Intent中可以配置多Category,Intent中的多个Category要在配置的Category中全部存在
Data的匹配规则
Manifest可配置多个Data,Intent只能配置一个Data,只要Intent中的Data和配置的一个Data匹配就可以,每个Data属性都可以指定数据的URI结构和数据MIME类型
URI包括scheme、host、port 和path四个部分,host和port合起来也成authority(host:port)
<scheme>://<host>:<port>/<path>

在URI中,每个组成部分都是可选的,但是有线性的依赖关系:如果没有scheme部分,那么host部分会被忽略,如果没有host部分,那么port部分会被忽略,如果host部分和port部分都没有,那么path部分会被忽略,当进行URI匹配时候,并不是比较全部,而是局部对比.
URI匹配规则
如果一个URI仅声明了scheme部分,那么所有拥有与其相同的scheme的URI都会通过匹配,其他部分不做匹配,如果一个URI声明了scheme部分和authority部分,那么拥有与其相同scheme和authority的URI才能匹配成功,path部分不做匹配,如果一个URI所有的部分都声明了,那么只有所有部分都相同的URI才能匹配成功
注意:path部分可以使用通配符(*),也就是path其中的一部分进行匹配。

MIME类型匹配规则
Manifest和Intent中的MIME要么都不存或者都存在且相同者匹配成功

Data匹配时候,URI和MIME类型两者都要匹配才可以
当有显示Intent存在时优先匹配显示Intent

二、组件的启动

Intent 中的Flags字段是用来告诉系统我们要以何种方式启动我们的组件,Flags是一个32位的整型数据,通过各个位的设置来表示不同的启动处理,影响启动方式的参数有taskAffinity,launchMode和Flags。

taskAffinity
默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名,具有相同的taskAffinity的activity属于同一个任务, 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task

launchMode

standard
在这种模式下启动的activity可以被多次实例化,即在同一个任务中可以存在多个activity的实例,每个实例都会处理一个Intent对象
singleTop
实例已经存在于任务桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例onNewIntent()方法将Intent对象传递到这个实例中
singleTask
1.设置了”singleTask”启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的任务存在;如果存在这样的任务,它就会在这个任务中启动,否则就会在新任务中启动。因此,如果我们想要设置了”singleTask”启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
2.如果设置了”singleTask”启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。
singleInstance
总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法。

Flags
FLAG_ACTIVITY_NEW_TASK 
设置此状态,记住以下原则,首先会查找是否存在和被启动的Activity具有相同的taskAffinity,如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。
FLAG_ACTIVITY_CLEAR_TOP 
Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B(堆栈状态: AB), 在Activity B中启动Activity C(堆栈状态: ABC), 在Activity C中启动Activity D(堆栈状态: ABCD), 在Activity D中启动Activity B, 启动Activity B的Intent的Flag设置为FLAG_ACTIVITY_CLEAR_TOP, (堆栈状态: AB)。
FLAG_ACTIVITY_SINGLE_TOP 
当前Task堆栈中存在ABCD四个Activity, A是栈顶Activity, D为栈底Activity, 存在打开A的Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志, 则会使用栈顶A, 而不会从新New A. 
注意如果在应用外启动应用内的activity,则要设置NEWTASK

其他参考:
Android官方文档或http://blog.csdn.net/lanxingf...

三、传递数据

Extras字段是Bundle类型用来存放要传递给组件的值,Bundle的内部是用一个 ArrayMap<String, Object>字段来存储数据。Bundle的封装主要是对数据类型做特定的限制,除了基础的数据类型外String,Parcelable,Serializable,或者上面类型组成的数组和List以及IBinder。

参考文章
https://segmentfault.com/a/11...
http://blog.csdn.net/luosheng...
http://blog.csdn.net/ljz2009y...
http://blog.csdn.net/qq_28331...


Lonestar
1 声望2 粉丝