Intent是什么?
Intent用于Android程序中各组件(Activity、BroadcastReceive、Service)的交互,并且可以在组件之间传递数据,分为显式Intent和隐式Intent。
显式Intent
通过Intent(Context packageContext, Class<?> cls)构造函数创建Intent实例,第一个参数为当前Context,第二个参数为要启动的目标类。如当需要启动OtherActivity时:
Intent intent=new Intent(MainActivity.this,OtherActivity.class);
startActivity(intent);
隐式Intent
不直接指明启动的目标,而是根据action和category找出合适的目标。可通过Mainfest.xml配置各组件的<intent-filter>,只有当<action>和<category>同时匹配时,才能响应对应的Intent。如在OtherActivity中配置:
<intent-filter>
<action android:name="testAction"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="testCategory"/>
</intent-filter>
当需要使用隐式Intent启动OtherActivity时:
Intent intent=new Intent("testAction");
intent.addCategory("testCategory");
startActivity(intent);
Tips:
- 不要忘记在<intent-filter>标签中配置android.intent.category.DEFAULT的category ,因为在调用startActivity()方法时会自动将这个category添加到Intent中,否则将报错android.content.ActivityNotFoundException: No Activity found to handle Intent
Intent扩展使用
在<intent-fliter>标签中配置<data>标签可以指定当前Intent可以响应数据类型。
- android:scheme:指定数据协议,如http、file、content,未指定时默认为file或content
- android:host:指定数据主机名,如www.baidu.com
- android:port:指定数据端口,如80
- android:path:指定端口后的路径
- android:pathPattern:同上,但可以加上通配符*
- android:pathPrefix:指定路径的前缀
- android:mineType:允许使用通配符进行指定
如通过显式Intent调用浏览器:
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
调用拨号界面
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
Intent传递数据
向下传递数据
Intent通过intent.putExtra(String,XXX)方法以键值对的方式传递数据,其中XXX可代表基本数据类型、数组等。如传递数据到OtherActivity:
Intent intent=new Intent(MainActivity.this,OhterActivity.class);
intent.putExtra("testdata","data");
startActivity(intent);
获取数据通过intent.getXXXExtra(String)方法,其中XXX可代表基本数据类型、数组等。如从OtherActivity中取出数据:
Intent intent = getIntent();
String testData = intent.getStringExtra("testdata");
Log.d("MainActivity", testData);
Tips:
- 在启动OtherActivity时如果需要传递数据,但OtherActivity并不是由你开发,不知道需要什么数据,此时你只能通过查看源码或询问同事,难免麻烦。通过将startActivity()和需要的数据再次封装就可解决上述问题:
public static void OtherActivityStart(Context context, String data1, String data2) {
Intent intent = new Intent(context, OhterActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
向上传递数据
通过startActivityForResult(Intent,int),第一个参数是启动目标活动的Intent,第二个参数是请求码,用于在回调中判断数据来源。如通过startActivityForResult启动OhterActivity:
Intent intent=new Intent(MainActivity.this,OhterActivity.class);
startActivityForResult(intent,1);
在OhterActivity通过setResult方法将数据返回(若想通过Back键返回,则将代码放置在onBackPressed方法中),第一个参数是返回的处理结果(RESULT_OK、RESULT_CANCELED),第二个参数是带有数据的Intent:
Intent intent=new Intent();
intent.putExtra("returnData","data");
setResult(RESULT_OK,intent);
finish();
OhterActivity销毁后,会回调上一个活动(MainActivity)的onActivityResult()方法,故我们需要重写该方法,通过判断请求码(数据来源)和处理结果从而获得数据进行相应操作:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if(resultCode==RESULT_OK){
Log.d("MainActivity", data.getStringExtra("returnData"));
}
break;
default:
}
}
Intent传递对象
Serializable
类通过实现Serializable接口,可以将对象转换成可存储或可传输的状态。
创建类Person:
public class Person implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
当需要传递时:
Person person = new Person();
person.setName("tom");
person.setAge(20);
Intent intent=new Intent(MainActivity.this,OhterActivity.class);
intent.putExtra("person",person);
startActivity(intent);
取出时:
Person person = (Person) getIntent().getSerializableExtra("person");
Parcelable
Parcelable通过将对象分解成Intent所支持的数据:
public class Person implements Parcelable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
protected Person(Parcel in) {
name = in.readString();
age = in.readInt();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
当需要传递时:
Person person = new Person();
person.setName("tom");
person.setAge(20);
Intent intent=new Intent(MainActivity.this,OhterActivity.class);
intent.putExtra("person",person);
startActivity(intent);
取出时:
Person person = (Person) getIntent().getParcelableExtra("person");