Intent 概述 翻译过来为“意图”,它是一种运行时绑定(run-time binding)机制,可以应用于两个应用间的通讯交互,也能够应用于在同一个应用下不同组件的交互(activity、service、broadcast receiver)
看下面的图,虽然Intent不属于四大组件,但是Intent却承担了三大组件的“中间人”的重任。试想一下,如果没有这个中间人,每一对组件间想要通信,就都需要重新开辟一条通道,随着组件数量和通讯需求的增加,这无疑会使得组件间的关系错综复杂,最后高度耦合,而加入这样一个中间人的角色,所有组件只需要联系这个中间人,由这个中间人去为组件进行匹配、传递等相关通信操作,这就使得组件间的依赖关系被极大的降低了。
(题外:Content Provide本身就是涉及进程通信的机制,所以用不到Intent)
对于向这三种组件发送intent有不同的机制:
使用Context.startActivity()或Activity.startActivityForResult(),传入一个intent来启动一个activity。 使用Activity.setResult(),传入一个intent来从activity中返回结果。 将intent对象传给Context.startService()来启动一个service或者传消息给一个运行的service。 将intent对象传给Context.bindService()来绑定一个service。 将intent对象传给Context.sendBroadcast(),Context.sendOrderedBroadcast(),或者Contex.sendStickyBroadcast()方法,则它们被传给 broadcast receiver。 然后上一段API对Intent的介绍
Intent 是一个消息传递对象,您可以使用它从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包括以下三个:
启动 Activity: Activity 表示应用中的一个屏幕。通过将 Intent 传递给 startActivity(),您可以启动新的 Activity 实例。Intent 描述了要启动的 Activity,并携带了任何必要的数据。 如果您希望在 Activity 完成后收到结果,请调用 startActivityForResult()。在 Activity 的onActivityResult() 回调中,您的 Activity 将结果作为单独的 Intent 对象接收。
启动服务: Service 是一个不使用用户界面而在后台执行操作的组件。通过将 Intent 传递给 startService(),您可以启动服务执行一次性操作(例如,下载文件)。Intent 描述了要启动的服务,并携带了任何必要的数据。 如果服务旨在使用客户端-服务器接口,则通过将 Intent 传递给 bindService(),您可以从其他组件绑定到此服务。
传递广播: 广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以将广播传递给其他应用。
组成部分 Intent由以下各个组成部分:
component(组件) :目的组件 Action (动作) :用来表现意图的行动 category (类别) :用来表现动作的类别 data (数据) :表示与动作要操纵的数据 type (数据类型) :对于data范例的描写 extras (扩展信息) :扩展信息 Flags (标志位) :期望这个意图的运行模式 更多细节可以参考API文档,传送门地址:
https://developer.android.google.cn/guide/components/intents-filters.html#Building
下面简单的对每个部分进行一定的介绍,具体肯定是👆的更具体。
component 即明确指定Intent的目标组件,这部描述再下面的显式Intent,不重复描述。
Action&Category Action用来表现意图的行动当日常生活中,描述一个意愿或愿望的时候,总是有一个动词在其中。
Category则为动作声明一个类别(给action增加额外的信息),常与action(难度不是必须吗?大雾)配套使用。
句子结构常常有主谓宾,Action即“谓语”,Category相当于“状语”
当你指明了一个Action,执行者就会依照这个动作的指示,接受相关输入,表现对应行为,产生符合的输出。 在Intent类中,定义了一批量的动作,比如 ACTION_VIEW, ACTION_PICK等, 基本涵盖了常用动作。 Action是一个用户定义的字符串,用于描述一个Android应用程序组件,一个Intent Filter可以包含多个Action。 在 AndroidManifest.ml的Activity定义时可以在其节点指定一个Action列表用于标识Activity所能接受的“动作”。 在Intent对象中add的Category属性,在Intent Filter中必须出现,否则会直接报错!! 相关Demo统一放下方的Demo一块,可以点击右侧目录进行跳转。
同时系统提供很多默认的Action常量,可以参考API文档
https://developer.android.google.cn/reference/android/content/Intent.html#standard-activity-actions
同样的,也提供了许多category的常量,可以参考如下:
https://developer.android.google.cn/reference/android/content/Intent.html#standard-categories
Data&Type Data即数据,表示要操纵的数据,声明方式类似Action&Category
Type即对data范例的描写
句子结构常常有主谓宾,Action即“宾语”,而Type可以理解为Application和activity的关系,有data那data的优先级就更高,没有就按type来。
data常配合action一起使用,来描述一个意图(想想宾语也是搭配谓语的),Data用一个uri对象(数据的地址,一种标识符)来表示。 如果Intent对象中既包含Uri又包含Type,那么,在sintent-filter>中也必须二者都包含才能通过测试。 Data属性的声明中要指定访问数据的Uri和MIME类型,Type属性则用于明确指定Data属性的数据类型或MIME类型。 通常来说,当Intent不指定Data属性时Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。 如果Intent对象包含Uri但是没有包含类型,并且类型不能从Uri中自动识别,那么cintent-filter>列表中也只能包含Uri 如果Intent对象只包含类型,没有包含Uri。那么,在sintent-filter>中也只能包含类型,不能包含Uri。 相关Demo统一放下方的Demo一块,可以点击目录进行跳转。
Extras 下面是API上的描述:
携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的 extra。
您可以使用各种 putExtra() 方法添加 extra 数据,每种方法均接受两个参数:键名和值。您还可以创建一个包含所有 extra 数据的 Bundle 对象,然后使用 putExtras() 将Bundle 插入 Intent 中。
例如,使用 ACTION_SEND 创建用于发送电子邮件的 Intent 时,可以使用 EXTRA_EMAIL 键指定“目标”收件人,并使用 EXTRA_SUBJECT 键指定“主题”。
Intent 类将为标准化的数据类型指定多个 EXTRA_* 常量。如需声明自己的 extra 键(对于应用接收的 Intent),请确保将应用的软件包名称作为前缀。 例如:
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"; Extras是其他所有附加信息的集合,可以为组件提供扩展信息。(传值的时候,就是使用它来传递简单对象、数据等等)
关于Demo可以参考之前的文章:
https://blog.csdn.net/nishigesb123/article/details/88900360
下面不再提供单独的演示
Flags 同样上一段API的描述
在Intent 类中定义的、充当 Intent 元数据的标志。 标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个任务),以及启动之后如何处理(例如,它是否属于最近的 Activity 列表)。
更多信息可以参考:
https://developer.android.google.cn/reference/android/content/Intent.html#setFlags(int)
实际上指的是Intent的运行模式,一个程序启动后系统会为这个程序分配一个task。
一个task里面可以拥有不同应用程序的activity,一个程序也可以对应多个task。
可以在AndroidManifest.xml中activity标签的属性launchMode中设置它们的对应关系(Activity的加载模式),一共有以下四种模式:
standard:标准模式,以这种模式加载必定会构造一个新的Activity实例放到目标task中的activity栈顶,不管当前 task的栈顶是什么情况。 singleTop: 与standard模式类似,区别在于加载activity会多个判断步骤。判断需要加载的新activity与当前 task栈顶的activity是不是同一个,相同的话就不再构造新的activity,并调用这个activity的newlnstance ()方法,不相同就还是会构造新的activity放到栈顶。 singleTask:该种模式下,会创建一个新的task来加iactivity,并且这个task中只允许存在一个Activity的一个实例(以后可以加载其他activity的实例) SingleInstance:这种模式下,会创建一个新的task并且这个task中只能存在一个需要加载的这个Activity实例,即除了这个activity之外,不允许其他activity。 关于 Activity 应该如何与任务关联 可以参考API地址如下:
https://developer.android.google.cn/guide/components/tasks-and-back-stack.html#ManifestForTasks
这部分内容比较多,所以单独放在另一篇文章(可能4.1号左右才可见):
https://blog.csdn.net/nishigesb123/article/details/88919008
下面不再提供单独的Demo演示
Intent大致可以分为两种, 显式和隐式,接下来我们逐个介绍。
显式Intent 显式 Intent 是指用于启动某个特定应用组件(例如,应用中的某个特定 Activity 或服务)的 Intent。
要创建显式 Intent,请为 Intent 对象定义组件名称 — Intent 的所有其他属性均为可选属性。
下面是一个简单的代码片段:
Intent intent = new Intent(MainActivity.this,YourActivity.class);
startActivity(intent); 可以看到,构建了一个Intent,传入了 MainActivity.this(上下文),YourActivity.class(目标活动,即component),即在MainActivity.this之上启动目标活动,如此一来,Intent非常明确,即称之为显示Intent。
目标活动可以是Class对,也可以是包名加类名的字符串。
隐式Intent 显示intent需要指定“接收者”和“发送者”,这不利于解耦,显然是和我们intent的初衷有一定矛盾之处的。
隐式就不一样了,Intent的发送者在构造Intent对象时,并不需要指定“接收者”,而是通过一定的设置,由系统进行筛选,这有助于解耦,所以官方也是推荐这种方式。
说到筛选,不难想到Filter(过滤器),确实,隐式Intent需要借助Intent Filter来实现“筛选”这一过程,并且仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。
下面是Intent Filter的匹配过程:
图片挂了...有机会补
DEMO 首先测试显式Intent,备注:除了该方式,接下来其余测试都是隐式。
测试之前准备一个Main2Activity,用于跳转,内容可以什么都不写。
再准备一个Button,并添加点击事件