Intent传递各种类型的数据
Intent传递简单数据:
我们可以直接通过调用Intent的putExtra()方法存入数据,然后在获得Intent后调用getXxxExtra获得 对应类型的数据;当我们要传递多个数据时,可以使用Bundle对象作为容器,通过调用Bundle的putXxx先将数据 存储到Bundle中,然后调用Intent的putExtras()方法将Bundle存入Intent中,然后获得Intent以后, 调用getExtras()获得Bundle容器,然后调用其getXXX获取对应的数据。
逐个传递数据:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//逐个发送
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("msg_str1","传递的数据");
intent.putExtra("msg_int1",100);
startActivity(intent);
}
});
//逐个接收
Intent intent = getIntent();
String name = intent.getStringExtra("msg_str1");
int age = intent.getIntExtra("msg_int1");
批量传送数据:
我们可以通过 Bundle 对象调用 Intent 的 putExtra 方法然后传递数据,Bundle 类默认也是已经实现了 Parcelable 接口的,我们可以直接传递 Bundle 对象
//批量传送
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putString("msg_str2", "这是一个数据");
bundle.putInt("msg_int2", 100);
//intent.putExtra("bundle",bundle);//1
intent.putExtras(bundle);//2
startActivity(intent);
}
});
//批量接收
//方法一
Bundle bundle = getIntent().getBundleExtra("bundle");
String name = bundle.getString("msg_str2");
int age = bundle.getInt("msg_int2");
//方法二
Bundle bundle = getIntent.getExtras();//2
Intent传递数组:
使用Intent我们是可以传递数组格式的数据:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
//写入数组://可把StringArray换成其他数据类型,比如int,float等等...
Bundle bundle = new Bundle();
bundle.putIntArray("arr_int",new int[]{1,2,3});
bundle.putStringArray("arr_str", new String[]{"呵呵","哈哈"});
}
});
//获取数据
Bundle bundle3=getIntent().getExtras();
int[] arr = bundle3.getIntArray("arr_int");
String[] str = bundle3.getStringArray("arr_str");
Intent传递集合:
和传递数组不同,传递集合相对比较复杂,需要分情况处理:
List<基本数据类型或String>
//写入集合:
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
ArrayList<String> list=new ArrayList<>();
list.add("HeHe");
intent.putStringArrayListExtra("list",list);
//读取集合:
Intent intent1=getIntent();
intent.getStringArrayListExtra("list");
List< Object>
:将list强转成Serializable类型,然后传入(可用Bundle做媒介)
//写入集合: Object类需要实现Serializable接口
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
Student student=new Student();
student.setName("张三");
student.setAge(20);
List<Student> list=new ArrayList<>();
intent.putExtra("student_list",(Serializable) list);
//读取集合
Intent intent1=getIntent();
List<Student> list1 =(List<Student>) getIntent().getSerializableExtra("student_list");
Map<String, Object>,或更复杂的集合,可以外层套个List进行传递
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
//传递复杂些的参数
Map<String, Object> map1 = new HashMap<String, Object>();
map1.put("key1", "value1");
map1.put("key2", "value2");
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
list.add(map1);
Bundle bundle = new Bundle();
//须定义一个list用于在bundle中传递需要传递的ArrayList<Object>,这个是必须要的
ArrayList bundleList = new ArrayList();
bundleList.add(list);
bundle.putParcelableArrayList("list",bundleList);
intent.putExtras(bundle);
startActivity(intent);
Intent传递对象:
传递序列化对象:
先将对象使用 Gson 先序列化成 Json 字符串,然后作为字符串来使用 Intent,这样我们不需要实现 Sereriable 或者 Paracelable,只需要解析Json字符串即可。
将对象转换为Json字符串,后传递数据:
创建实体类:
public class Student{
private String name;
private int age;
/*
* Get、Set
*/
}
传递数据:
//写入数据:
Student student=new Student();
student.setName("张三");
student.setAge("20);
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("student",new Gson().toJson(student));
startActivity(intent);
//读取数据:
String studentJson=getIntent().getStringExtra("student");
Student student=new Gson().fromJson(studentJson,Student.class);
使用Serializable实现传递对象:
Serializable是序列化的意思,表示将一个对象转换成可存储可传输的状态。序列化之后的对象可以在网络上进行传输,也可以存储到本地。想要事项序列化,我们只需要实现序列化接口即可。
使用方法:
- ①业务Bean实现:Serializable接口,写上getter和setter方法
- ②Intent通过调用putExtra(String name, Serializable value)传入对象实例 当然对象有多个的话多个的话,我们也可以先Bundle.putSerializable(x,x);
- ③新Activity调用getSerializableExtra()方法获得对象实例: eg:Product pd = (Product) getIntent().getSerializableExtra(“Product”);
- ④调用对象get方法获得相应参数
样例:
public class Student implements Serializable {
private String name;
private int age;
/*
* Get、Set
*/
}
//发送数据:
Student student=new Student();
student.setName("张三");
student.setAge(20);
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("student_data",student);
startActivity(intent);
//接收数据
Student student1=(Student)getIntent().getSerializableExtra("student_data");
使用Parcelable实现传递对象:
使用方法:
- ①业务Bean继承Parcelable接口,重写writeToParcel方法,将你的对象序列化为一个Parcel对象;
- ②重写describeContents方法,内容接口描述,默认返回0就可以
- ③实例化静态内部对象CREATOR实现接口Parcelable.Creator
- ④同样式通过Intent的putExtra()方法传入对象实例,当然多个对象的话,我们可以先 放到Bundle里Bundle.putParcelable(x,x),再Intent.putExtras()即可
注意:写入的 顺序和读取的顺序必须一致。
样例:
实现Parcelable接口的代码示例:
public class Student implements Parcelable {
private String name;
private int age;
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeInt(age);
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
Student student=new Student();
student.name=in.readString();
student.age=in.readInt();
return student;
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
}
//发送数据:
Student student=new Student();
student.setName("张三");
student.setAge(20);
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("student_data",student);
startActivity(intent);
//接收数据,通过调用getParcelableExtra方法获取传递过来的对象
Student student1=(Student)getIntent().getParcelableExtra("student_data");
两种序列化方式的比较:
Serializable相对来说实现比较简单,由于把整个对象进行序列化,性能较低,考虑到性能的话推荐使用Parcelable。但是Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下,此时建议使用Serializable。
Intent详解
组件间的枢纽——Intent(意图),Android通信的桥梁,比如我们可以通过:
- startActivity(Intent)/startActivityForResult(Intent):来启动一个Activity
- startService(Intent)/bindService(Intent):来启动一个Service
- sendBroadcast:发送广播到指定BroadcastReceiver
Intent是由action(动作)、data(数据)、类型(type)、component(组件)、Flags(标记)和Extra(扩展信息)等内容组成,每个组成都由相应属性进行表示,并提供设置和获取相应属性的方法。
Component属性:
Component属性用于指明Intent目标组件的类名称,它可以被设置,也可以不被设置。如果不设置Component属性,该Intent称之为隐式Intent,Android会根据Intent中包含的其他属性信息,比如Action、Data/Type、Category进行查找,最终找到一个与之匹配的目标组件。如果设置Component属性,则该Intent成为显式Intent,显示Intent则会根据组件名查找到相应的组件,不再执行上述查找过程。
Data属性:
Data属性通常是用于向Action属性提供操作的数据。Data属性有两部分构成分别是数据的URI和数据的MIME类型。
Category属性:
Category属性指明一个执行Action的分类,一个Intent对象最多只能包含一个Action属性,但是可以包含多个Category属性。调用Intent.setAction()方法来说设置Action属性值,调用Intent.addCategory()方法为Intent添加Category属性。
显式Intent与隐式Intent:
- 显式Intent:通过组件名指定启动的目标组件,比如startActivity(new Intent(A.this,B.class)); 每次启动的组件只有一个
- 隐式显式Intent:不指定组件名,而指定Intent的Action,Data,或Category,当我们启动组件时, 会去匹配AndroidManifest.xml相关组件的Intent-filter,逐一匹配出满足属性的组件,当不止一个满足时, 会弹出一个让我们选择
显式Intent使用示例
Intent 意图,用于启动Activity、启动服务、发送广播等,承担了Android应用程序三大组件的通信功能。显式意图,启动Activity时明确指定激活组件的名称。
IntentFilter
如果Intent Filter定义的动作、类别、数据(URI和数据类型)与Intent匹配,就会使用Intent Filter所在的组件来处理该Intent。
- 第一种,在Intent的构造方法中指定被启动的Activity
Intent intent=new Intent(this,B.class);
startActivity(intent); - 第二种,根据目标组件的包名、全路径名来指定开启组件
Intent intent=new Intent();
intent.setClassName(“包名”,”全路径名”);
startActivity(intent); - 第三种,通过设置Intent的Component属性
ComponentName com=new ComponentName(A.this,B.class);
Intent intent=new Intent();
intent.setComponent(com); startActivity(intent);
点击按钮返回Home界面:
Intent it = new Intent();
it.setAction(Intent.ACTION_MAIN);
it.addCategory(Intent.CATEGORY_HOME);
startActivity(it);
点击按钮打开百度页面:
Intent it = new Intent();
it.setAction(Intent.ACTION_VIEW);
it.setData(Uri.parse("http://www.baidu.com"));
startActivity(it);
隐式Intent:
隐式Intent没有明确指定组件名。而是系统根据动作(action)、类别(category)、数据(Uri和数据类型)来找到最合适的组件。
使用隐式意图开启Activity的示例代码如下:
Intent intent=new Intent();
intent.setAction();
startActivity(intent);
显式意图开启组件时必须要指定组件的名称,一般只在本应用程序中切换组件时使用。而隐式意图的功能要比显示意图更加强大,不仅可以开启本应用的组件,还可以开启其他应用的组件,例如打开系统的照相机、浏览器等。