赞
踩
翻译过来为“意图”,它是一种运行时绑定(run-time binding)机制,可以应用于两个应用间的通讯交互,也能够应用于在同一个应用下不同组件的交互(activity、service、broadcast receiver)
看下面的图,虽然Intent不属于四大组件,但是Intent却承担了三大组件的“中间人”的重任。试想一下,如果没有这个中间人,每一对组件间想要通信,就都需要重新开辟一条通道,随着组件数量和通讯需求的增加,这无疑会使得组件间的关系错综复杂,最后高度耦合,而加入这样一个中间人的角色,所有组件只需要联系这个中间人,由这个中间人去为组件进行匹配、传递等相关通信操作,这就使得组件间的依赖关系被极大的降低了。
(题外:Content Provide本身就是涉及进程通信的机制,所以用不到Intent)
对于向这三种组件发送intent有不同的机制:
然后上一段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由以下各个组成部分:
更多细节可以参考API文档,传送门地址:
https://developer.android.google.cn/guide/components/intents-filters.html#Building
下面简单的对每个部分进行一定的介绍,具体肯定是?的更具体。
即明确指定Intent的目标组件,这部描述再下面的显式Intent,不重复描述。
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即数据,表示要操纵的数据,声明方式类似Action&Category
Type即对data范例的描写
句子结构常常有主谓宾,Action即“宾语”,而Type可以理解为Application和activity的关系,有data那data的优先级就更高,没有就按type来。
相关Demo统一放下方的Demo一块,可以点击目录进行跳转。
下面是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
下面不再提供单独的演示
同样上一段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的加载模式),一共有以下四种模式:
关于 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 是指用于启动某个特定应用组件(例如,应用中的某个特定 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对象时,并不需要指定“接收者”,而是通过一定的设置,由系统进行筛选,这有助于解耦,所以官方也是推荐这种方式。
说到筛选,不难想到Filter(过滤器),确实,隐式Intent需要借助Intent Filter来实现“筛选”这一过程,并且仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。
下面是Intent Filter的匹配过程:
图片挂了...有机会补
首先测试显式Intent,备注:除了该方式,接下来其余测试都是隐式。
测试之前准备一个Main2Activity,用于跳转,内容可以什么都不写。
再准备一个Button,并添加点击事件
- <Button
- android:id="@+id/button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="componentClick"
- android:text="通过组件名称直接查找组件"
- app:layout_constraintTop_toTopOf="parent"
- />
书写点击事件方法
- //显式(指定组件名称)
- public void componentClick(View view){
- Intent intent = new Intent();
- ComponentName componentName = new ComponentName(this,Main2Activity.class);
- intent.setComponent(componentName);
- //等价于 Intent intent = new Intent(this,Main2Activity.class);
- startActivity(intent);
- }
点击后成功跳转到Main2Activity
接着测试Action&Category
测试之前准备一个Main3Activity,用于跳转,内容可以什么都不写,为了标识,加了个TextView。
同样准备一个Button,并添加点击事件
- <Button
- android:id="@+id/button_action"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="actionClick"
- android:text="通过Action查找组件"
- app:layout_constraintTop_toBottomOf="@id/button"
- />
书写点击事件方法
- //隐式(通过action)
- public void actionClick(View view){
- Intent intent = new Intent();
- //参数为字符串,理论上可以随便写,规范点加上包名(大雾)
- intent.setAction("com.example.a3_30intent.action.MY_ACTION");
- //同样可以合并成一行 Intent intent = new Intent("com.example.a3_30intent.action.MY_ACTION");
- //指定category
- //intent.addCategory("com.example.a3_30intent.action.MY_Category");
- startActivity(intent);
- }
进入配置清单文件(AndroidManifest.xml)
在Main3Activity部分加入intent-filter
定义子项action,为其name赋值com.example.a3_30intent.action.MY_ACTION(setAction的那个参数)
需要注意的:
最后还要加上一句配置category的语句(可以暂时理解成默认格式....)
注意:如果当前组件是Activity,并且没有指定的category,必须加上category并使用默认的DEFAULT!!!如下:
<category android:name="android.intent.category.DEFAULT"></category>
- <activity android:name=".Main3Activity">
- <intent-filter>
- <action android:name="com.example.a3_30intent.action.MY_ACTION"></action>
- <category android:name="android.intent.category.DEFAULT"></category>
- </intent-filter>
- </activity>
点击后成功跳转到Main3Activity
可以试着在之前的Main2Activity的配置文件也加入
- <action android:name="com.example.a3_30intent.action.MY_ACTION"></action>
- <category android:name="android.intent.category.DEFAULT"></category>
即,有两个符合的Activity,
可以看到系统会弹出选择框,示意你从两个中选一个...(感觉还是给Main3Activity设置一下label比较好...不然名字显示是application的label...)
可以通过android:priority来设置优先级(本身是数字越大优先级越高,但是在此处,除非有一个数字为负数,比如一个为1,一个为2,优先级将视相同,即依旧会弹出提示框让用户选择)
- <activity
- android:name=".Main3Activity">
- <intent-filter android:priority="-1">
- <action android:name="com.example.a3_30intent.action.MY_ACTION"></action>
- <category android:name="android.intent.category.DEFAULT"></category>
- </intent-filter>
- </activity>
- <activity
- android:name=".Main2Activity"
- android:label="@string/title_activity_main2"
- android:theme="@style/AppTheme.NoActionBar" >
- <intent-filter android:priority="2">
- <action android:name="com.example.a3_30intent.action.MY_ACTION"></action>
- <category android:name="android.intent.category.DEFAULT"></category>
- </intent-filter>
- </activity>

接下来关于data&type
再准备一个Main4Activity,用于跳转,内容可以什么都不写。
依旧需要一个Button,并添加点击事件
- <Button
- android:id="@+id/button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="componentClick"
- android:text="通过组件名称直接查找组件"
- app:layout_constraintTop_toTopOf="parent"
- />
书写点击事件方法
由于setdata参数是Uri,所以需要定义一个Uri。
- //隐式(通过data)一般配合action
- public void dataClick(View view){
- Intent intent = new Intent();
- intent.setAction("com.example.a3_30intent.action.MY_ACTION");
- //Uri data = Uri.fromFile();
- Uri data = Uri.parse("http://www.baidu.com");
- //参数为一个uri
- intent.setData(data);
- startActivity(intent);
- }
然后是配置文件
需要配置如下属性
android:scheme(协议,如http)
- android:host(具体的地址,如本例中的www.baidu.com)
- android:path(具体的路径,如果是www.baidu.com/abc/abc...则可以再补path,实际上好像path可以代替host?)
- <activity
- android:name=".Main4Activity"
- android:label="@string/title_activity_main4"
- android:theme="@style/AppTheme.NoActionBar">
- <intent-filter android:priority="1">
- <action android:name="com.example.a3_30intent.action.MY_ACTION" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="http" android:host="www.baidu.com"></data>
- </intent-filter>
- </activity>
点击后成功跳转到Main4Activity
如果不使用自定义的action,而是使用默认的如intent.ACTION_VIEW
并在配置文件清单加入
<action android:name="android.intent.action.VIEW" />
可能还需要设置以下语句,否则飘红线...
<category android:name="android.intent.category.BROWSABLE"/>
可以看到会打开浏览器(也可能是出来一个选择,选用浏览器还是直接在Main4Activity打开)
访问百度...(← ←甭管地址栏,虽然访问的是www.baidu.com但是它自己重定向了)
下面再设置type
首先我们观察一下setData方法和setType方法在系统中的定义
- public @NonNull Intent setData(@Nullable Uri data) {
- mData = data;
- mType = null;
- return this;
- }
-
-
- public @NonNull Intent setType(@Nullable String type) {
- mData = null;
- mType = type;
- return this;
- }
可以发现,setData方法中默认Type被设置为null,setType方法中Data被设置为null
显然他俩是相互矛盾的,所以想两个方法该怎么办呢?
系统提供了一个
intent.setDataAndType()方法
- public @NonNull Intent setDataAndType(@Nullable Uri data, @Nullable String type) {
- mData = data;
- mType = type;
- return this;
- }
我们使用它就可以同时对type和data进行设置了
测试代码如下:
intent.setDataAndType(data,"text/html");
配置文件:
- <activity
- android:name=".Main4Activity"
- android:label="@string/title_activity_main4"
- android:theme="@style/AppTheme.NoActionBar">
- <intent-filter android:priority="1">
- <action android:name="com.example.a3_30intent.action.MY_ACTION" />
- <action android:name="android.intent.action.VIEW" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.BROWSABLE"/>
- <data android:scheme="http" android:host="www.baidu.com" android:mimeType="text/html"></data>
- </intent-filter>
- </activity>
测试效果和原来没有差别,所以实际上type并不常用....效果不算明显
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。