android Intent 机制

一. Intent 对象

1.1什么是Intent

首先呢,大家要明确一点android时基于组件的应用开发。所以,开发过程中我们不仅要寻找和构造符合需求的组件,更重要的是,要将组件有机的连接起来,互相交换信息,这样才能构建出我们最终想要的应用程序。所以,intent便是用来组件之间连接并通信的模式。

1.2.Intent 的构成

(1) Action项(谓语)
在Intent对象中用Action来表达动作,当调用组件指定一个Action后,执行组件就会按照这个Action的指示执行相关操作;
(2) Data项(宾语)
当调用组件(主语)发起请求时,如果该组件有明确的数据对象,通常就会用Data项来进行存储。
(3) TypeData用于描述具体操作目标的需求,例如:“我(调用组件)喝(Action动作)王老吉(Data项)”。而Type就用于表示“我喝饮料”。即:Data用于特指,而Type用于泛指。
(4) Category项
Category用于表述在特定场合下的约束条件。例如:“当我口渴的时候,我喝王老吉”,说明“口渴了”是“喝王老吉”这个Intent的条件。
(5) Component项
Component项指的是目标组件的类型信息。制定了Component后,Intent就变成了单纯的信息载体只负责传递消息和数据。
(6) Extras项
Extras项是Intent数据传输的载体负责将数据从调用组件传递到实现组件。
(7)    Flags 项
Flags是一个整型数,是调用组件指定组件管理服务构造实现组件的方式。

1.3.Intent 的分类

(1) 在意图机制中,组件管理服务负责接受和分析Intent对象,为调用组件选择最合适的实现组件。从实现组件的选择来看,Intent对象可以分成两类:精确描述的 Intent(Explicit Intent-显示Intent)和模糊描述的Intent(Implicit Intent -隐式Intent)。

1.4 Intent Filter 对象

Intent Filter是各个组件用于描述其功能的,通过组建的Intent Filter信息,android组件管理应用就可以掌握各个组件所具备的能力和可以处理的请求。而且,Intent Filter对象的每个数据项的结构和含义,与Intent中的数据项一一对应。

二. Intent匹配

1.Intent 匹配的算法流程

1.1 Action 的比较:
每个Intent Filter 对象都必须包含Action信息,如果没有,则对任何一个Intent对象,都会匹配失败。
1.2 DataType 的比较
1.3 Category 的比较

三. Intent 的使用

1.显式调用

显式调用时必须制定组件名称,例如:

Intent intent = new Intent();
intent.setClass(A.this,B.class);        //指定了调用组件和实现组件
A.this.startActivity(intent);

2.隐式调用

(1)隐式调用并传递Extra附加数据与静态广播的使用

首先实现Intent的调用代码

Intent intent_BroaadCast = new Intent("Intent_1112");
intent_BroaadCast.putExtra("StringTest", "LA_LA_LA");
MainActivity.this.sendBroadcast(intent_BroaadCast);

实现静态BroadCastReceiver

package me.androiddemo.canglangwenyue.androiddemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**
 * Created by canglangwenyue on 15-3-5.
 */
public class TestBroadCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,                         intent.getExtras().getString("StringTest"),Toast.LENGTH_LONG).show();
    }
}

注册Receiver

<receiver android:name=".TestBroadCastReceiver">
    <intent-filter>
        <action android:name="Intent_1112"></action>
    </intent-filter>
</receiver>

注意:再manifest中注册时action的name应与Intent intent_BroaadCast = new         Intent("Intent_1112");中的name保持一致。

(2) 隐式调用并传递Extra附加数据与动态广播的使用

 首先,新建一个BroadCastReceiverpackage me.androiddemo.canglangwenyue.androiddemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**
 * Created by canglangwenyue on 15-3-5.
 */
public class MyBroadCast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

                                                    Toast.makeText(context,intent.getExtras().getString("StringTest"),
                                                    Toast.LENGTH_LONG
).show();

    }
}

其次,再Activity的onCreate中动态添加IntentFilter,并注册BroadCastReceiver;并在
onStop中取消该BroadCastReceiverIntentFilter filter = new IntentFilter();
private MyBroadCast broadCast = new MyBroadCast();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    filter.addAction("MyBroadCast");
    registerReceiver(broadCast, filter);

}

 @Override
protected void onStop() {
    unregisterReceiver(broadCast);
    super.onStop();
}

使用该类型Intent的代码:

  Intent intent_ActiveBroaadCast = new Intent();
intent_ActiveBroaadCast.putExtra("StringTest", "阿哈");
intent_ActiveBroaadCast.setAction("MyBroadCast");
MainActivity.this.sendBroadcast(intent_ActiveBroaadCast);

(3) 不使用广播的Intent

 除了广播来触发IntentAction外,我们还可以使用startActivity()方法来实现相同功能。

     public void ButtonClick4(View view) {

    /**
     * 注意:
     * 此处因为有动态声明的BroadCastReceiver,所以运行改方法后程序会奔溃,但是此处因为时范        例,便于对比,所以我并没有新建project
     */

    Intent intent_ActiveBroaadCast = new Intent("myTest111");
    intent_ActiveBroaadCast.putExtra("StringTest", "德玛西亚");
    MainActivity.this.startActivity(intent_ActiveBroaadCast);
}      

   然后我们必须在该intent想要启动的实现组件中添加IntentFilter来截获,否则就无法匹配到实现组件。

   <activity
        android:name=".Activity2"
        android:label="@string/title_activity_activity2" >
        <intent-filter>
            <action android:name="myTest111"></action>
            <category android:name="android.intent.category.DEFAULT"></    category>
        </intent-filter>
    </activity> 
需要注意的是:首先,action name应该保持一致;其次,必须声明
<categoryandroid:name="android.intent.category.DEFAULT"></category>,因为,我们在
使用intent时并没有指定category,所以,系统默认添加了DEFAULT,故如果不在<intent-filter>进
行声明,则无法匹配到Activity。

(4) 使用系统自带的一些标准Action,这里只列举一二:

 获取联系人列表

    Uri uri = Uri.parse("content://contacts");
    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, uri);
      pickContactIntent.setType(ContactsContract.CommonDataKinds.
      Phone.CONTENT_TYPE); //         Show user only contacts w/ phone numbers
    startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);  

拨打电话

    Uri number = Uri.parse("tel:187008*****");
    Intent callIntent = new Intent(Intent.ACTION_CALL, number);

    startActivity(callIntent);

四. Intent 传输数据
android 界面组件间通过要通过Intent来实现,Intent传递数据的方式有两种