Android Intent学习

前言

Intent组件虽然不是四大组件,但却是连接四大组件的桥梁,学习好这个知识,也非常的重要。

一、什么是Intent

1Intent的概念:

  • Android中提供了Intent机制来协助应用间的交互与通讯,或者采用更准确的说法是,Intent不仅可用于应用程序之间,也可用于应用程序内部的activity, servicebroadcast receiver之间的交互。Intent这个英语单词的本意是目的、意向、意图
  • Intent是一种运行时绑定(runtime binding)机制,它能在程序运行的过程中连接两个不同的组件。通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来响应。

activityservicebroadcast receiver之间是通过Intent进行通信的,而另外一个组件Content Provider本身就是一种通信机制,不需要通过Intent

2、对于向这三种组件发送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(),或者Context.sendStickyBroadcast()等广播方法,则它们被传给 broadcast receiver

二、Intent的相关属性:

  • Intent由以下各个组成部分:
  • component(组件):目的组件
  • action(动作):用来表现意图的行动
  • category(类别):用来表现动作的类别
  • data(数据):表示与动作要操纵的数据
  • type(数据类型):对于data范例的描写
  • extras(扩展信息):扩展信息
  • Flags(标志位):期望这个意图的运行模式

Intent类型分为显式Intent(直接类型)、隐式Intent(间接类型)。官方建议使用隐式Intent。上述属性中,component属性为直接类型,其他均为间接类型。

相比与显式Intent,隐式Intnet则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定一系列更为抽象的actioncategory等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。

1component(组件):目的组件

Component属性明确指定Intent的目标组件的类名称。(属于直接Intent

如果 component这个属性有指定的话,将直接使用它指定的组件。指定了这个属性以后,Intent的其它所有属性都是可选的。

例如,启动第二个Activity时,我们可以这样来写:

button1.setOnClickListener(new OnClickListener() {                        @Override          
    public void onClick(View v) {                 //创建一个意图对象  
                        Intent intent = new Intent();        //创建组件,通过组件来响应                 
                        ComponentName component = new             
                        ComponentName(MainActivity.this, SecondActivity.class);
                        intent.setComponent(component);             
                        startActivity(intent);                             }        });

         

 

如果写的简单一点,监听事件onClick()方法里可以这样写:

     Intent intent = new Intent();  //setClass函数的第一个参数是一个Context对象                                       
    intent.setClass(MainActivity.this, SecondActivity.class);          
    startActivity(intent);        

再简单一点,可以这样写:(当然,也是最常见的写法)

 Intent intent = new Intent(MainActivity.this,SecondActivity.class);               

 startActivity(intent);

2Action(动作):用来表现意图的行动

当日常生活中,描述一个意愿或愿望的时候,总是有一个动词在其中。比如:我想三个俯卧撑;我要一封情书,等等。在Intent中,Action就是描述做、写等动作的,当你指明了一个Action,执行者就会依照这个动作的指示,接受相关输入,表现对应行为,产生符合的输出。在Intent类中,定义了一批量的动作,比如ACTION_VIEWACTION_PICK等, 基本涵盖了常用动作。加的动作越多,越精确。

Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml Activity 定义时,可以在其 <intent-filter >节点指定一个 Action列表用于标识 Activity 所能接受的动作

3category(类别):用来表现动作的类别

Category属性也是作为<intent-filter>子元素来声明的。例如:

<intent-filter>

  <action android:name="com.vince.intent.MY_ACTION"></action>

  <category android:name="com.vince.intent.MY_CATEGORY"></category> 

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

</intent-filter>

Action category通常是放在一起用的,所以这里一起介绍一下。我们来先来举一个例子:

新建一个工程文件smyh006_Intent01,在默认文件的基础之上,新建文件SecondActicity.javaactivity_second.xml

紧接着,我们要到清单文件中进行注册,打开AndroidManifest.xml,添加SecondActivityactioncategory的过滤器:

<activity   android:name=".SecondActivity">            
    <intent-filter>             
     <actionandroid:name="com.example.smyh006intent01.MY_ACTION"/>
     <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>

上方代码,表示SecondActicity可以匹配第4行的MY_ACTION这个动作,此时,如果在其他的Acticity通过这个action的条件来查找,那SecondActicity就具备了这个条件。类似于相亲时,我要求对方有哪些条件,然后对方这个SecondActicity恰巧满足了这个条件(够通俗了吧)。

上述情况只有SecondActicity匹配成功。如果有多个组件匹配成功,就会以对话框列表的方式让用户进行选择。我们来详细介绍一下:

我们新建文件ThirdActicity.javaactivity_third.xml,然后在清单文件AndroidManifest.xml中添加ThirdActivityactioncategory的过滤器:

  <activity  android:name=".ThirdActivity">         
  <intent-filter>
    <action android:name="com.example.smyh006intent01.MY_ACTION"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

做出如下总结:

在自定义动作时,使用activity组件时,必须添加一个默认的类别

具体的实现为:

<intent-filter>

               <action android:name="com.example.action.MY_ACTION"/>

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

</intent-filter>

如果有多个组件被匹配成功,就会以对话框列表的方式让用户进行选择。

每个Intent中只能指定一个action,但却能指定多个category;类别越多,动作越具体,意图越明确(类似于相亲时,给对方提了很多要求)。

目前我们的Intent中只有一个默认的category,现在可以通过intent.addCategory()方法来实现。修改MainActivity中按钮的点击事件,代码如下:

button1.setOnClickListener(new OnClickListener() {      
@Override 3
       public void onClick(View v) { //启动另一个Activity,(通过action属性进行查找)
       Intent intent = new Intent();
//设置动作(实际action属性就是一个字符串标记而已)
        intent.setAction("com.example.smyh006intent01.MY_ACTION");
//方法:Intent android.content.Intent.setAction(String action)
      intent.addCategory("com.example.smyh006intent01.MY_CATEGORY");
        startActivity(intent);
}});

既然在Intent中增加了一个category,那么我们要在清单文件中去声明这个category,不然程序将无法运行。代码如下:

  <android:name=".SecondActivity"> 
<intent-filter>
     <action android:name="com.example.smyh006intent01.MY_ACTION"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.smyh006intent01.MY_CATEGORY" />
</intent-filter>
</activity>

此时,点击MainActicity中的按钮,就会跳到SecondActicity中去。

总结如下:

自定义类别: Intent添加类别可以添加多个类别,那就要求被匹配的组件必须同时满足这多个类别,才能匹配成功。操作Activity的时候,如果没有类别,须加上默认类别

4data(数据):表示与动作要操纵的数据

  • Data属性是Android要访问的数据,和actionCategory声明方式相同,也是在<intent-filter>中。
  • 多个组件匹配成功显示优先级高的; 相同显示列表。

Data是用一个uri对象来表示的,uri代表数据的地址,属于一种标识符。通常情况下,我们使用action+data属性的组合来描述一个意图:做什么

使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得Android多个应用程序之间的功能共享成为了可能。比如应用程序中需要展示一个网页,没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要条用系统的浏览器来打开这个网页就行了。

 

我们可以总结如下:

  • Intent匹配成功的组件有多个时,显示优先级高的组件,如果优先级相同,显示列表让用户自己选择
  • 优先级从-10001000,并且其中一个必须为负的才有效

注:系统默认的浏览器并没有做出优先级声明,其优先级默认为正数。

优先级的配置如下:

在清单文件中修改对SecondAcivity的声明,即增加一行代码,通过来android:priority设置优先级,如下:

  <activity  android:name=".SecondActivity">
<intent-filter android:priority="-1">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="www.baidu.com"/>
</intent-filter>
</activity>

注:

Data属性的声明中要指定访问数据的UriMIME类型。可以在<data>元素中通过一些属性来设置:

android:schemeandroid:pathandroid:portandroid:mimeTypeandroid:host等,通过这些属性来对应一个典型的Uri格式scheme://host:port/path。例如:http://www.google.com

5type(数据类型):对于data范例的描写

如果Intent对象中既包含Uri又包含Type,那么,在<intent-filter>中也必须二者都包含才能通过测试。

Type属性用于明确指定Data属性的数据类型或MIME类型,但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。

datatype属性一般只需要一个,通过setData方法会把type属性设置为null,相反设置setType方法会把data设置为null,如果想要两个属性同时设置,要使用Intent.setDataAndType()方法。

 

6extras(扩展信息):扩展信息

是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行发送电子邮件这个

动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

 

7Flags(标志位):期望这个意图的运行模式

一个程序启动后系统会为这个程序分配一个task供其使用,另外同一个task里面可以拥有不同应用程序的activity。那么,同一个程序能不能拥有多个task?这就涉及到加载activity的启动模式,这个需要单独讲一下。

注:android中一组逻辑上在一起的activity被叫做task,自己认为可以理解成一个activity堆栈。

 

三、Activity的启动模式:

Activity四种启动模式:standardsingleTopsingleTasksingleInstance。可以在AndroidManifest.xmlactivity标签的属性android:launchMode中设置该activity的加载模式。

  • standard模式:默认的模式,以这种模式加载时,每当启动一个新的活动,必定会构造一个新的Activity实例放到返回栈(目标task)的栈顶,不管这个Activity是否已经存在于返回栈中;
  • singleTop模式:如果一个以singleTop模式启动的activity的实例已经存在于返回桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中;

注:如果以singleTop模式启动的activity的一个实例已经存在于返回桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例;

  • singleTask模式:这种模式下,每次启动一个activity时,系统首先会在返回栈中检查是否存在该活动的实例,如果存在,则直接使用该实例,并把这个活动之上的所有活动统统清除;如果没有发现就会创建一个新的活动实例;
  • singleInstance模式:总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重新调用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例。(singleInstance即单实例)

注:前面三种模式中,每个应用程序都有自己的返回栈,同一个活动在不同的返回栈中入栈时,必然是创建了新的实例。而使用singleInstance模式可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪一个应用程序来访问这个活动,都公用同一个返回栈,也就解决了共享活动实例的问题。(此时可以实现任务之间的切换,而不是单独某个栈中的实例切换)

posted on 2019-06-13 01:37  feibin筱飞  阅读(478)  评论(0)    收藏  举报