1、Intent是一个将要执行的动作的抽象描述,一般是用来协助完成各个组件之间的通讯。Intent负责对应用中一次操作的动作及动作涉及的数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成对组件的调用。可以说,Intent起着媒介的作用,专门提供提供组件相互调用的相关信息,实现调用者和被调用者之间的控制。
2、Intent的构成
1)Action:用来指明要实施的动作是什么。如ACTION_VIEW, ACTION_EDIT等
2)Data:具体的数据,一般由Uri变量来表示
3)Category:指定将要执行的这个action的其它一些额外的信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。
4)Type:显示指定Intent的数据类型。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
5)Component:指定Intent的目标组件的类名称。通常Android会根据Intent中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。
6)Extra:附加信息,是其它所有附加信息的集合。使用extras可以为组件提供扩展信息。比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
3、Intent中data数据的Uri结构
android采用指向数据的一个URI来表示数需要操作的数据。
URI主要分三部分:scheme、authority和path,其中authority可分为host和port。格式:scheme://host:port/path
实例如下:
content://com.example.project:200/folder/subfolder/etc
\---------/ \---------------------------/ \---/ \--------------------------/
scheme host port path
\--------------------------------/
authority
4、Intent解析
应用程序的组件为了告诉Android自己能响应、处理哪些隐式Intent请求,可以声明一个甚至多个Intent Filter。每个Intent Filter描述该组件所能响应Intent请求的能力——组件希望接收什么类型的请求行为,什么类型的请求数据。比如之前请求网页浏览器这个例子中,网页浏览器程序的Intent Filter就应该声明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及与之相关的请求数据是网页地址URI格式。如何为组件声明自己的Intent Filter? 常见的方法是在AndroidManifest.xml文件中用属性< Intent-Filter>描述组件的Intent Filter。
<activity android:name="com.example.learn.MainActivity" android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
5、android解析Intent的流程
在应用中具体分成两种Intent:直接Intent 和 间接Intent。
直接intent就是指定了component属性的intent(调用setComponent(componentName))。通过指定具体的组件类,通知应用启动对应的组件;
间接intent是没有指定component属性的intent,这些intent需要包含足够的信息,这样系统才能确定启动对应的组件;
对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将Intent映射给可以处理此Intent的Activity、Broadcaset receiver或Service。Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:
● 如果intent指明了action,则目标组件的intentFilter的action列表就必须包含有这个action,否则不能匹配;
● 如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。
● 如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme(比如 http: 或者mailto:)进行匹配。同上,Intent 的scheme必须出现在目标组件的scheme列表中。
● 如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEG
ORY,解析得到的目标组件必须至少包含这两个类别。
6、catetory的类别总结:
android.intent.category.ALTERNATIVE:ALTERNATIVE 种类指定,在某种数据类型的项目上可以替代默认执行的动作。例如,一个联系人的默认动作时浏览它,替代的可能是去编辑或删除它。
android.intent.category.BROWSABLE:指定在浏览器中的动作。当 Intent 在浏览器中被引发,都会被指定成 BROWSABLE 种类。
android.intent.category.DEFAULT
android.intent.category.DEVELOPMENT_PREFERENCE
android.intent.category.EMBED
android.intent.category.HOME:HOME Activity 是设备启动(登陆屏幕)时显示的第一个 Activity 。通过指定 Intent Filter 为 HOME 种类而不指定动作的话,你正在将其设为本地 home 画面的替代。
android.intent.category.INFO
android.intent.category.LAUNCHER:使用这个种类来让一个 Activity 作为应用程序的启动项。
android.intent.category.MONKEY
android.intent.category.OPENABLE
android.intent.category.PREFERENCE
android.intent.category.SELECTED_ALTERNATIVE:与 ALTERNATIVE 类似,但 ALTERNATIVE 总是使用下面所述的 Intent 解析来指向单一的动作。SELECTED_ALTERNATIVE在需要一个可能性列表时使用。
android.intent.category.TAB
7、Intent有两种基本用法:一种是显示的Intent,即在构造intent对象时就指定接收者,这种方式与普通的函数调用类似。另一种是隐式的intent,即intent的发送者在构造intent对象时,但是并不关心接收者,有利于降低发送者和接收者之间的耦合。
8、bundle
android使用Intent.putSerializable()进行数据传递,或者使用Bundle进行数据传递。实质上都是进行的Serializable数据的操作,都是传递源数据的一份拷贝。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 定义一个Bundle按键
Button gotoBundle = (Button)findViewById(R.id.btnBundle);
// 设置监听事件
gotoBundle.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(getApplicationContext(), GetBundleActivity.class);
DataBean temp = new DataBean();
temp.setID(1);
temp.setName("张三");
temp.setAddress("xx市xx路xx号");
temp.setMoblie("159xxxxxxxx");
Log.i("AndroidbundleActivity", "新建时候的地址" + temp);
Bundle bundle = new Bundle();
bundle.putSerializable("UserInfo", temp);
// 设置intent
intent.putExtras(bundle);
// 发送Activity
getApplicationContext().startActivity(intent);
}
});
}
public void onCreate(Bundle savedInstanceState) {
// 初始化BundleActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.bundle);
// 获取意图
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
// 获取对象
DataBean temp = (DataBean) bundle.get("UserInfo");
Log.i("GetBundleActivity", "收到的地址" + temp);
}
9、intent实例
1)无参数activity跳转
Intent intent = new Intent(Activity.Main.this, Activity2.class);
startActivity(intent);
2)向下一个activity传递数据(使用bundle和putExtras)
Intent intent = new Intent(Activity.Main.this, Activity2.class);
Bundle bundle=new Bundle();
bundle.putString("name", "This is from MainActivity!");
intent.putExtras(bundle);
//startActivity(intent);
startActivityForResult(intent,REQUEST_CODE);
Bundle bundle=getIntent().getExtras();
String name=bundle.getString("name");
3)向上一个Activity返回结果(使用setResult,针对 startActivityForResult(it,REQUEST_CODE)启动的Activity)
Intent intent=getIntent();
Bundle bundle=new Bundle();
bundle.putString("name", "This is from Activity2!");
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
注解:
startActivityForResult(Intent intent, Int requestCode):requestCode >=0就好,随便用于在onActivityResult()区别哪个子模块回传的数据,如果还有C.java ,D甚至E子模块的话,每个区分开不同的requestCode就好。
setResut(int resultCode, Intent intent):resultCode 如果B子模块可能有几种不同的结果返回,可以用这个参数予以识别区分。这里还有个特殊的 RESULT_OK 值,没有特殊情况用它就好了。intent 传回给A的onActivityResult()
onActivityResult(int requestCode, int resultCode, Intent intent):如果不对requestCode和resultCode 加以识别区分的话,只要有其他activity setResult到了A
onActivityResult()会无差别处理。
4)回调上一个Activity的结果处理函数(onActivityResult)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==REQUEST_CODE){
if(resultCode==RESULT_CANCELED)
setTitle("cancle");
else if (resultCode==RESULT_OK) {
String temp=null;
Bundle bundle=data.getExtras();
if(bundle!=null)
temp=bundle.getString("name");
setTitle(temp);
}
}
}