Android笔记02:Intent机制详解

一、什么是Intent?

Intent在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”,专门提供组件互相调用的相关信息。

二、Intent的作用

Intent 是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。比如说调用 startActivity()来启动一个activity,或者由broadcaseIntent()来传递给所有感兴趣的 BroadcaseReceiver, 再或者由startService()/bindservice()来启动一个后台的service.所以可以看出来,intent主要是用来启动其他的 activity 或者service,所以可以将intent理解成activity之间的粘合剂。

三、Intent的两种类型

Intent大致可以分为两种类型:显式Intent和隐式Intent。

显式Intent:

如果在我们定义的Intent中明确包含了要启动的组件的完整类名(包名及类名),即Intent的“意图”非常明显,那么这个Intent就是显式的。使用显式Intent最典型的情形是在你自己的程序中启动一个组件,因为你自己肯定知道自己的要启动的组件的类名。比如,为了响应用户操作通过显式的Intent在你的程序中启动一个Activity或启动一个Service下载文件。

隐式Intent:

没有明确指定组件名要启动哪一个活动,而是系统根据动作(action)、类别(category)、数据(Uri)和数据类型来找到最合适的组件。一般来说我们需要在<intent-filter>里设置category、action和data等信息。需要注意的是,为了确保App的安全性,我们应该总是使用显式Intent去启动Service并且不要为该Service设置任何的Intent Filter。通过隐式的Intent启动Service是有风险的,因为你不确定最终哪个App中的哪个Service会启动起来以响应你的隐式Intent,更悲催的是,由于Service没有UI的在后台运行,所以用户也不知道哪个Service运行了。

Intent Filter,即Intent过滤器,一个组件可以包含0个或多个Intent Filter。Intent Filter是写在App的manifest文件中的,其通过设置action或uri数据类型等指明了组件能够处理接收的Intent的类型。

隐式Intent的具体方法:

<activity

           android:name=".ThreeActivity"

           >

            <intent-filter >

                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <data android:scheme="http"/>

            </intent-filter>

</activity>

其中<action>标签指明了当前活动可以响应的action。<category>标签则附加了一些信息,更精确地指明了当前活动能响应的Intent还可能带有的category。只有<action>和<category>同时匹配上Intent中指定的action和category时,活动才能响应该Intent。

<data>标签能够更精确地指定当前活动能够响应什么类型的数据。

<data>标签中主要可以配置一下内容:

android:scheme。用于指定数据的协议部分,如http。

android:host。用于指定数据的主机名部分。

android:port。用于指定数据的端口部分,一般在主机名之后。

android:path。用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。

android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

只用当<data>标签中指定的内容和Intent中携带的data部分完全一致时,当前活动才能够响应intent。

 

显式Intent示例:

Intent intent = new Intent(this, ActivityB.class);
startActivity(intent);

上面的代码在Intent的构造函数中指定了要启动的组件的ComponentName是ActivityB,该intent对象是显式的,调用startActivity(intent)时,Android系统会立即启动ActivityB。

隐式Intent示例:

在使用隐式Intent的时候需要指定其action。如果你的App不能完成某个功能,但是其他的App可能完成该功能,那么你就可以用隐式Intent启动其他的App去完成相应的功能。例如,你有一段文本信息,想通过其他App分享出去,那么隐式Intent对象去启动潜在的支持分享的App,示例代码如下:

Intent sendIntent = new Intent();
// 设置action, action对隐式Intent来说是非常重要的
sendIntent.setAction(Intent.ACTION_SEND);
// 设置数据的MIME类型为纯文本类型
sendIntent.setType("text/plain");
// 设置额外的数据
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);

// 获取包管理器
PackageManager pm = getPackageManager();
// 先判断系统中有没有潜在的App的Activity支持对该sendIntent的接收与处理
if (pm.resolveActivity(sendIntent, 0) != null) {
    startActivity(sendIntent);
}

上面的代码中,我们构建了一个Intent对象,并没有给其设置component name,所以该Intent是一个隐式的Intent对象。我们首先给intent设置了action的值为Intent.ACTION_SEND,action对隐式Intent来说是非常重要的。然后我们将intent的数据的MIME类型设置为纯文本类型(“text/plain”),告知Android我们的Intent持有的是文本类型的数据。最后我们将实际的文本数据通过putExtra()方法作为额外数据设置进去。 
需要注意的是,在构建好了Intent对象之后,我们没有立即执行startActivity(sendIntent)方法,而是将sendIntent作为参数传递给了PackageManager的resolveActivity()方法中,该方法会让Android根据该sendIntent找到潜在的适合启动的组件的信息,并以ResolveInfo类的对象的形式返回结果,如果返回null,表示当前系统中没有任何组件可以接收并处理该sendIntent。如果返回不是null,就表明系统中至少存在一个组件可以接收并处理该sendIntent,只有在这种情况下,我们才会执行代码startActivity(sendIntent),在通过intent启动组件之前先判断要启动的组件存不存在是个良好的编程习惯,因为如果系统中不存在支持你的intent的组件,那么当你调用startActivity()、startService()、bindService()等方法的时候,Android就会抛出异常。

 (后续还会有修改和补充)

猜你喜欢

转载自www.cnblogs.com/alyssayoung/p/8971111.html