Android的Intent机制

Intent对象的作用和构成

android意图机制最核心的设计思想,就是引入了组件管理服务作为连接组件的管理者。 该服务的作用:

  • 通过组件的配置信息了解系统中每个组件的类别和功能
  • 帮助调用组件寻找符合其需求的实现组件,将调用者与实现在彻底解耦

在整个意图机制下,有三方角色参与组件间的连接和通信

【调用组件】连接请求的发起者,它期望寻找其他组件来帮助完成所需的功能。通过调用startActivity和bindService等函数发起对目标组件的连接请求

【实现组件】响应调用者请求完成所需任务的组件,每个组件都可以作为调用者请求第三方帮助,也都可以扮演实现着去完成对应的请求。对于实现组件而已,不需要关注其调用者是谁,只需依照请求者发送的Intent对象去执行相关功能即可

【组件管理服务】在调用组件与实现组件的连接过程中,组件管理服务扮演了调度者的角色。从调用组件中接收到Intent对象,然后将该对象与应用管理服务收集到的组件Intent Filter对象进行比较,从中选择出符合调用组件需求的实现组件,最后构造并调用实现组件对象,组件管理服务是一个系统服务,运行在系统核心进程的独立线程中,通过进程间通信机制,与各组件进行交互

Intent对象的作用

Intent对象是组件间通信信息的载体。它封装了调用组件提供的指令和数据,通过组件管理服务序列化传递给实现组件,实现组件可以利用这些信息完成所需功能。 Intent对象定义了组件间连接协议。每个Intent对象都包含若干个数据项,每个数据项都有其内涵,调用者组件根据这些规范构造Intent对象描述其需求;实现组件根据这些规范解析Intent对象执行所需功能;而组件管理服务依照这些规范寻找与需求匹配的组件,构造连接

Intent对象的构成

Intent类的实现非常简单,只是包含了若干个数据项

  • Action项 Action就是用来表达动作的。Action就是一个字符串,可以用setAction函数为intent对象指定一个动作,也可以用getAction读取Intent对象中的动作信息。
  • Data项 意愿的表达,比如我吃宫保鸡丁,主语“我”,在意图机制下对应着调用组件,谓语“吃”,用Intent的Action对象来表达,宾语"宫保鸡丁"则对应着Data,setData,setDataAndType来进行设置,通过getData函数来读取。Data数据也是用字符串进行存储的,它的个数符合URI标准,URI具有丰富的表达能力,能够表达存储在任何地方的数据
  • Type项 如果Data用于特指,那么Type用于泛指,setType,setDataAndType,getType,Type是MIME格式的字符串数据,用于描述组件能够处理的请求类型,或者补充说明Data数据的类型。可以通过通配符*来表示整个类别的信息 在Intent对象中,Data项和Type项很多时候是互斥使用的。一个Intent中,需要Data表示数据还是用Type表示数据类型通常是和Action密切相关的。
  • Category项 category表示约束,每个Intent对象可包含多个Categories。addCategory添加Category项,getCategories获取该Intent对象Category项的集合。同一个Intent中的多个Category项彼此间是"与"关系。也就是说一个组件需要支持全部的Category项才能处理该请求。
  • Component项 Component指的是目标组件的类型信息,通过setComponent方法利用类名进行设定,也可以通过setClass方法利用类型对象信息进行设置。当调用组件明确了Component信息,组件管理服务就不再需要根据Action、Data等信息去寻找满足其需求的实现组件了。只需按照Component信息实例化对于的组件作为功能实现者即可。
  • Extras项 Extras是Intent中数据传输的载体,负责将数据从调用组件传递到实现组件。Extras是一个Bundle对象,该对象按照键值对的方式存储数据,它实现了Parcelable接口,可以进行数据的序列化和反序列化,从而在进程中传递。
  • Flags项 一个整形数,由一系列的标志位汇集而成。它对于实现组件而言完全透明,是调用组件指定组件管理服务构造实现组件的方式,常用于改变实现组件的任务模型和进程模型等。被设定的Flags标志位将会叠加生效。但需要注意的是,很多标志位之间是相关联逻辑关系的,有的标志位需要同时设定,而有的标志位直接则具有一定的互斥性。

Intent对象解析

组件管理服务负责接收和分析Intent对象。Intent对象可以分成两类:精确描述的Intent(Explicit Intent)和模糊描述的Intent(Implicit Intent) 精确描述的Intent,指的是所有带有Component信息的Intent对象。在精确描述的前提下,Intent对象只是作为消息的载体存在 模糊描述的Intent,对基于模糊描述的Intent调用组件而言,它们不在乎实现组件是谁,只要求该组件能够依照Intent对象中描述的意图和需求完成对应的任务。 精确描述的Intent通常用于应用内部的通信,因为调用组件和实现组件彼此了解,不需要动态机制,只需要最快地将消息传递过去就好了。 而模糊描述的Intent,则用于不同应用组件间的互联互通,它的存在将请求者和实现者完全解耦,极大地提升了系统的灵活性。

Intent Filter对象

与Intent相似,IntentFilter对象也包含Action、Type、Data、Category等数据项,每个数据项的结构和含义,与Intent中的数据项也一一对应。当组件管理服务接收到调用组件发送来的基于模糊描述的Intent对象时,会与所有组件的IntentFilter信息进行匹配技术,寻找符合需求的实现组件。 每个组件都可以有任意数量的IntentFilter,组件包含的Intent Filter对象越多,说明它能接受Intent请求的范围越广。而不添加任何Intent Filter对象的组件,仅能通过Intent对象精确地进行调用 组件对于的IntentFilter信息,一般通过配置文件的项进行添加,放在界面组件、服务组件或触发器组件的配置项中。

意图匹配的算法流程

Intent对象和Intent Filter对象的匹配过程,就称为意图匹配算法。

算法输入的是进行比较的Intent对象和Intent Filter对象,输出的是一个32位的整数值,用于表征两者的匹配程度。整个匹配算法的流程可分为3个步骤 1. Action的比较:每个IntentFilter对象都必须包含Action信息,如果没有,则对任何一个Intent对象都会匹配失败 2. Data和Type的比较:Data和Type信息是Intent Filter中最复杂的数据项,其比较算法是决定Intent与Intent Filter对象匹配程度的关键 3. Category的比较

匹配组件的选择

如果有多个Intent Filter对象与调用组件发出的Intent对象都相匹配,就需要在所有符合条件的Intent Filter对象中进行筛选,选出最符合调用组件和用户需求的实现组件,这个流程就称为匹配组件的选择。 在组件选择上,最核心的机制就是基于优先级的排序。每一个Intent Filter对象都有一个优先级,从-1000到1000,值越大,优先级越高 实例例子,如拦截短信,可以采取提升Intent Filter优先级的策略来实现:

    <receiver android:name="third_parth.SmsReceiver">        <intent-filter>            <action android:priority="1000"                android:name="android.provider.Telephony.SMS_RECEIVED"/>        </intent-filter>    </receiver>

在third_party.SmsReceiver这个触发组件中,系统可以定制策略拦截特定的短信,通过调用abortBroadcast()函数终止广播,使其他短信应用的Intent Filter无法匹配短信通知

public void onReceive(Context context,Intent intent){    if(IsBlockSms(intent))        abortBroadcast();}

意图匹配的优化

意图机制中,引入第三方组件管理服务,降低了调用组件和实现组件之间的耦合,提高了系统的灵活性及组件的复用性,但同时,由于第三方服务地介入增加了组件间连接的成本,可能会使组件间的调用不够流畅。因此,系统对组件的匹配和选择过程进行了大量的优化,以提升意图匹配和组件调用的效率。

  • 索引:此流程涉及大量的字符串比较,比较耗时。组件管理服务会通过哈希表,为所有Intent Filter对象的Action、Type等数据项建立索引。每个索引对应着一组Action相同,Type相同,或者其他数据项相同的Intent Filter对象。Intent对象会先将其中的数据项与索引项进行比较,快速地选择出可能与Intent相匹配的Intent Filter对象。
  • 缓存:将Intent和Intent Filter的匹配结果记录下来,当再碰到相同的Intent的调用时,可直接返回上次记录的结果,从而跳过意图匹配的过程,加速组件的调用。服务组件,组件管理服务会在内存中通过哈希表的形式保留各个Intent对应的服务组件。

意图机制的应用

意图机制在界面组件中的应用

调用组件可以通过调用startActivity和startActivityForResult等函数发起对目标界面组件的调用,选择并构造出一个符合其需求的界面组件实例,切换至前台与用户进行交互。调用组件可以在构造的Intent对象中添加一些Flags标志位信息,用于告知组件管理服务如何去构造实现组件。当多个界面组件都能满足调用组件的需求,就需要从中选择一个最适合的组件作为最终的实现组件。对于界面组件的选择,需要兼顾效率和公平性。

  • 效率:选择过程中尽可能流畅
  • 公平性:每个符合调用者需求的组件,都应当具有同等的权利来响应调用组件的请求。 首先,通过算法对已排序的Intent Filter进行筛选,组件管理服务会将排序后队列中的第一个Intent Filter对象(记为A)与第二个Intent Filter对象(记作B)进行比较,如果满足一下条件中的一个,组件管理服务就会直接选择A对象对应的组件作为实现组件
  • A的优先级高于B
  • A包含intent.CATEGORY_DEFAULT,而B没有 同时,Android会将所有符合需求的组件列举起来,让用户决定选择哪个组件来执行该操作。用户可以选择该组件作为执行类似Intent调用的默认组件 如果调用组件期望绕过默认值的约束,让用户根据当前场景再次做出选择,可以通过Intent.createChooser方法自定义组件选择列表 activity.startActivity(Intent.createChooser(intent,R.strng.invite_friend));

意图机制在服务组件中的应用

调用组件可以调用Context.startService函数启动符合需求的服务组件,也可以通过Context.bindService函数绑定对应的服务组件。由于服务组件是在后台提供服务的,当出出现多个匹配项时,无法像界面组件一样构造交互界面让用户来抉择。因此,Android会默认选择优先级最高的组件作为实现组件。 这种情况下,只要备选组件没有变化,对于同一个Intent对象而言,其实现组件是固定的,因此,组件管理服务会记录Intent对象与其实现组件的对照关系,当再次通过相同的Intent对象请求服务时,就可以跳过组件匹配计算,直接返回实现组件。

意图机制在触发器组件中的应用

触发器组件的功能就是监听广播事件的Intent对象,并对其进行简单的解析和处理。调用组件调用sendBroadcast或sendOrderedBroadcast函数进行事件的广播。这些事件消息的载体就是Intent对象 用于广播事件中的Intent对象的Action项,与用于界面组件调用中Intent对象的Action项是完全分离的。 在触发器组件的构造中,不存在匹配组件选择的问题。

小结

Android的意图机制是Android应用模型的核心,解决了组件间的连接问题。通过组件管理服务提供的Intent对象与Intent Filter对象的匹配策略,降低了组件间的耦合度,提供了平台的灵活性,增强了组件的复用性,从而从根本上减轻了应用开发的负担。

更多相关文章

  1. android内存问题详解--重要
  2. H264解码器源码(Android(安卓)1.6 版和QT都可以调用)
  3. Android中的Cursor到底是什么?如何理解Cursor的方法都在做什么事
  4. android OpenGL开发 一个爆炸效果的粒子发生器
  5. TensorFlow在Android平台上的安装和应用
  6. Android实战项目——音乐播放器 由四大组件之一Service、使用Ser
  7. 2016年末,Android岗位BAT等大厂面试题知识点小结(一)Android基础部
  8. State 状态模式在 Android(安卓)多弹窗的应用
  9. Android监听ListView停止的时候是不是滑动到底部

随机推荐

  1. 【Android开发经验】兼容不同的屏幕大小(
  2. 在android中使用文件进行数据存储
  3. android用Intent传输自定对象数组(Parcel
  4. ActionBar使用
  5. Android圆形图片控件RoundedImageView
  6. GrideView简单使用
  7. android usb解析(一)UsbDeviceManager(and5
  8. android使用GestureDetector实现手势下滑
  9. Android(安卓)交叉编译 i2c-tools
  10. Android(安卓)如何避免(降低)后台程序被杀?