Intent详解及其用法

您所在的位置:网站首页 电脑三大主件 Intent详解及其用法

Intent详解及其用法

2024-07-17 17:03| 来源: 网络整理| 查看: 265

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,并添加点击事件

书写点击事件方法

//显式(指定组件名称) 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,并添加点击事件

书写点击事件方法

//隐式(通过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的那个参数)

 

需要注意的:

一个Activity是可以指定多个action属性的一个Activity也可以指定多个category属性一个Intent只能指定一个action一个intent可以指定多个category

 

最后还要加上一句配置category的语句(可以暂时理解成默认格式....)

注意:如果当前组件是Activity,并且没有指定的category,必须加上category并使用默认的DEFAULT!!!如下:

点击后成功跳转到Main3Activity

 

可以试着在之前的Main2Activity的配置文件也加入

即,有两个符合的Activity,

可以看到系统会弹出选择框,示意你从两个中选一个...(感觉还是给Main3Activity设置一下label比较好...不然名字显示是application的label...)

可以通过android:priority来设置优先级(本身是数字越大优先级越高,但是在此处,除非有一个数字为负数,比如一个为1,一个为2,优先级将视相同,即依旧会弹出提示框让用户选择)

 

接下来关于data&type

再准备一个Main4Activity,用于跳转,内容可以什么都不写。

依旧需要一个Button,并添加点击事件

书写点击事件方法

由于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?)

点击后成功跳转到Main4Activity

如果不使用自定义的action,而是使用默认的如intent.ACTION_VIEW

并在配置文件清单加入

可能还需要设置以下语句,否则飘红线...

可以看到会打开浏览器(也可能是出来一个选择,选用浏览器还是直接在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");

配置文件:

测试效果和原来没有差别,所以实际上type并不常用....效果不算明显

 



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3