intent用于组件之间的跳转,它在程序运行时连接两个组件;intent分为显式intent和隐式intent,显式intent常用在本应用之间组件的跳转,隐式intent常用于在不同应用之间组件的跳转。通过Intent,你可以向Android提交一个请求,Android会根据Intent的意愿来选择合适的组件来响应请求。这篇文章不会介绍不同应用通过intent之间数据的传递,介绍显式Intent与隐式Intent
Intent对象
这里介绍显式Intent和隐式Intent
指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context, Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。通过指定目标组件名字,寻找目标组件,一般应用于调用程序和目标组件在同一个应用中的情况;
显式Intent通过指定组件来直接调用的,Intent中可以通过下面的方式实现显式Intent
setComponent(ComponentName name)
Component类是Android系统提供的组件封装类,需要提供包名,类名,context对象setClassName(String packageName,String classNameInThatPackage)
提供类名和本包中目标组件类名–必须是全类名,包名+类名setClassName(Context context,String classNameInThatContext)
Context对象和目标组件类名–必须是全类名,包名+类名,setClassName中会创建一个Conponent对象,而Component对象如果传入的是context对象的话,会通过context.getPackageName()来获取包名setClass(Context context,Class classObjectInThatContext)
Context对象和目标组件类类型,与fnew Intent(MainActivity.this,OtherActivity.class);
传递的参数一样我们经常使用显式Intent的方式是通过Intent构造函数来创建的,如下所示:
Intent intent=new Intent(MainActivity.this,OtherActivity.class);
查看源代码可以知道,构造函数内部所做的事情是新创建了一个ComponentName对象,如下图:
构造函数new了一个ComponentName对象,并赋值给这个mComponent(后面都使用mComponent来指定intent创建出的ComponentName对象)。之后通过startActivity(intent)
来启动目标组件,当我们不传递任何参数创建Intent对象时,就需要我们手动设置ComponentName对象,与上述通过传递context对象和Class对象相同,代码如下:
Intent intent=new Intent(MainActivity.this,OtherActivity.class);
ComponentName com=new ComponentName("com.sujz.intent_test","com.sujz.intent_test.OtherActivity"));
intent.setComponent(com)
startActivity(intent);
ComponentName对象传递两个参数,第一参数传递的是当前Activity对象所在的包名,第二个参数传递的是目标对象的全类名(包名+类名)
setComponentName
方法实际上是给上图中的mComponent赋值。所以通过setComponentName方法上述方法一样
setClassName
与setComponent
类似,setClassName
内部会构造一个ComponentName对象,然后赋值给mComponent对象,其他的方法不再赘述。
隐式Intent对象是没有指定mComponent的Intent,也就是说,在构建Intent的过程中,不会通过Intent intent=new Intent(MainActivity.this,OtherActivity.class);
, setComponent(ComponentName name)``setClassName(String packageName,String classNameInThatPackage)``setClass(Context context,Class classObjectInThatContext)
等方式来指定ComponentName对象,注意是不会,不会,不会,重要的事情说3遍。
当没有指定mComponent对象时,需要足够的信息才能够匹配到目标组件,这些信息包括Action,Category,Data。这3个信息需要当前组件的Intent和目标组件的Intent都配置,只要当两个组件的3个信息匹配时,才会启动目标组件,当然也可能会同时匹配到多个目标组件,这时就需要用户自己去选择,如下边的栗子,就是一个Intent匹配到了多个目标组件。这种方式不仅可以启动本应用中的相关组件,也可以启动其他应用的相关组件,举个栗子,当我们的手机中安装了多个浏览器时,比如UC,百度等,当我们在某个应用中点击某个链接时,是不是会跳出一个选择框来让你选择使用哪个浏览器来打开链接(如果没有弹出选择框,有两个可能:1.你的手机只有一个浏览器。2.你之前勾选了默认使用该浏览器打开链接)。好了,栗子举完了。来说正事,这种方式就是通过隐式Intent来设置的。那我们要怎么设置来启动另外一个组件呢?继续看。
首先我们先将目标组件的Intent设置,刚刚说到我们在匹配时,需要当前组件和目标组件都设置了Intent,目标组件的Intent设置在AndroidManifest.xml中。在这里我们有两个应用程序,一个是Intent_test,另一个是Host,现在从Host启动到Intent_test,也就是说目标组件时Inent_test中的MainActivity1是目标组件,我们需要在AndroidManifest中配置如下:
<activity
android:name="com.sujz.intent_test.MainActivity1"
android:label="@string/title_activity_main_activity1" >
<intent-filter>
<action android:name="com.sujz.aa" />
<category android:name="android.intent.category.DEFAULT" />
intent-filter>
activity>
在目标组件的AndroidManifest中,在该Activity节点下需需要配置intent-filter节点,该节点至少需要配置一个Action和一个Category,action和Category可以有多个,只需要匹配到其中某一个即可,这里没有配置Data,也就是说Data可以不配置。主要这里必须要配置
原因是因为在发送intent请求的组件中默认会配置这一项。
Host中的代码如下:
Intent intent=new Intent();
intent.setAction("com.sujz.aa");
startActivity(intent);
可能有人会问,这里没有配置category,为什么能匹配到。这是因为android在startActivity(intent)中会设置category。内部会调用intent.addCategory("android.intent.category.DEFAULT");
setAction中需要传递目标组件的Intent-filter的action名称。
你也可以创建自己的category,以上面为例,如下所示,在intent_test中:
<activity
android:name="com.sujz.intent_test.MainActivity1"
android:label="@string/title_activity_main_activity1" >
<intent-filter>
<action android:name="com.sujz.aa" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.bb" />
intent-filter>
activity>
在Host中:
Intent intent=new Intent();
intent.setAction("com.sujz.aa");
intent.addCategory("android.intent.category.bb");
startActivity(intent);
不需要intent.addCategory("android.intent.category.DEFAULT");
因为在startActivity(intent);
已经添加了。
好了隐式Intent已经讲完了