Android中的Serialable和Parcelable的区别
转:http://blog.csdn.net/jiangwei0910410003/article/details/18988673
一.先从Serialize说起
我们都知道JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
二、Android中的新的序列化机制
在Android系统中,定位为针对内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC(进程间通信)机制,必然要求使用性能更出色的对象传输方式。在这样的环境下,Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。
三、Android中的Serialable和Parcelable的区别
1、作用
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
从上面的设计上我们就可以看出优劣了。
2、效率及选择
Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化
3、编程实现
对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。而Parcelable则需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。
Parcelable的一个实现例子如下
[java] view plaincopyprint?
- publicclass MyParcelable implements Parcelable {
- privateint mData;
- private String mStr;
- publicint describeContents() {
- return 0;
- }
- // 写数据进行保存
- publicvoid writeToParcel(Parcel out, int flags) {
- out.writeInt(mData);
- out.writeString(mStr);
- }
- // 用来创建自定义的Parcelable的对象
- publicstatic final Parcelable.Creator
CREATOR - = new Parcelable.Creator
() { - public MyParcelable createFromParcel(Parcel in) {
- return new MyParcelable(in);
- }
- public MyParcelable[] newArray(int size) {
- return new MyParcelable[size];
- }
- };
- // 读数据进行恢复
- private MyParcelable(Parcel in) {
- mData = in.readInt();
- mStr = in.readString();
- }
- }
publicclass MyParcelable implements Parcelable { privateint mData; private String mStr; publicint describeContents() { return 0; } // 写数据进行保存 publicvoid writeToParcel(Parcel out, int flags) { out.writeInt(mData); out.writeString(mStr); } // 用来创建自定义的Parcelable的对象 publicstatic final Parcelable.Creator CREATOR = new Parcelable.Creator() { public MyParcelable createFromParcel(Parcel in) { return new MyParcelable(in); } public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } }; // 读数据进行恢复 private MyParcelable(Parcel in) { mData = in.readInt(); mStr = in.readString(); } }
从上面我们可以看出Parcel的写入和读出顺序是一致的。如果元素是list读出时需要先new一个ArrayList传入,否则会报空指针异常。如下:
list= new ArrayList
in.readStringList(list);
PS: 在自己使用时,read数据时误将前面int数据当作long读出,结果后面的顺序错乱,报如下异常,当类字段较多时务必保持写入和读取的类型及顺序一致。
11-2120:14:10.317: E/AndroidRuntime(21114): Caused by: java.lang.RuntimeException:Parcel android.os.Parcel@4126ed60: Unmarshalling unknown type code 3014773 atoffset 164
4、高级功能上
Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义
四、Parcelable应用
Parcelable是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此会更加高效。
我们接下来要说的是Parcel类如何应用。就应用程序而言,最常见使用Parcel类的场景就是在Activity间传递数据。没错,在Activity间使用Intent传递数据的时候,可以通过Parcelable机制传递复杂的对象。
下面来看一下简单的代码:
UserInfo类,实现了Parcelable接口:
[java] view plaincopyprint?- package com.demo.entity;
- import java.util.ArrayList;
- import java.util.HashMap;
- import android.os.Parcel;
- import android.os.Parcelable;
- /**
- * 用户信息,实现Parcelable接口
- * String,int,String[],ArrayList
>这四种类型测试 - * @author weijiang204321
- *
- */
- public class UserInfo implements Parcelable{
- private String id;
- private String name;
- private int age;
- private String[] boyfriendAry = new String[3];
- private ArrayList
> listData = new ArrayList >(); - private SonInfo sonInfo;
- public UserInfo(){
- }
- public UserInfo(String id,String name,int age,String[] boyfriendAry,ArrayList
> listData){ - this.id = id;
- this.name = name;
- this.age = age;
- this.boyfriendAry = boyfriendAry;
- this.listData = listData;
- }
- public UserInfo(Parcel source){
- id = source.readString();
- name = source.readString();
- age = source.readInt();
- sonInfo = source.readParcelable(SonInfo.class.getClassLoader());
- source.readStringArray(boyfriendAry);
- source.readList(listData, SonInfo.class.getClassLoader());
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- 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;
- }
- public SonInfo getSonInfo(){
- return sonInfo;
- }
- public void setSonInfo(SonInfo sonInfo){
- this.sonInfo = sonInfo;
- }
- public String[] getBoyfriendAry() {
- return boyfriendAry;
- }
- public void setBoyfriendAry(String[] boyfriendAry) {
- this.boyfriendAry = boyfriendAry;
- }
- public ArrayList
> getListData() { - return listData;
- }
- public void setListData(ArrayList
> listData) { - this.listData = listData;
- }
- @Override
- public int describeContents() {
- return 0;
- }
- //进行序列化存储
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(id);
- dest.writeString(name);
- dest.writeInt(age);
- dest.writeParcelable(sonInfo, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- dest.writeStringArray(boyfriendAry);
- dest.writeList(listData);
- }
- public static final Parcelable.Creator
CREATOR = new Creator () { - @Override
- public UserInfo[] newArray(int size) {
- return new UserInfo[size];
- }
- //将Parcel对象反序列化为UserInfo
- @Override
- public UserInfo createFromParcel(Parcel source) {
- return new UserInfo(source);
- }
- };
- }
package com.demo.entity;import java.util.ArrayList;import java.util.HashMap;import android.os.Parcel;import android.os.Parcelable;/** * 用户信息,实现Parcelable接口 * String,int,String[],ArrayList>这四种类型测试 * @author weijiang204321 * */public class UserInfo implements Parcelable{private String id;private String name;private int age;private String[] boyfriendAry = new String[3];private ArrayList> listData = new ArrayList>();private SonInfo sonInfo;public UserInfo(){}public UserInfo(String id,String name,int age,String[] boyfriendAry,ArrayList> listData){this.id = id;this.name = name;this.age = age;this.boyfriendAry = boyfriendAry;this.listData = listData;}public UserInfo(Parcel source){id = source.readString();name = source.readString();age = source.readInt();sonInfo = source.readParcelable(SonInfo.class.getClassLoader());source.readStringArray(boyfriendAry);source.readList(listData, SonInfo.class.getClassLoader());}public String getId() {return id;}public void setId(String id) {this.id = id;}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;}public SonInfo getSonInfo(){return sonInfo;}public void setSonInfo(SonInfo sonInfo){this.sonInfo = sonInfo;}public String[] getBoyfriendAry() {return boyfriendAry;}public void setBoyfriendAry(String[] boyfriendAry) {this.boyfriendAry = boyfriendAry;}public ArrayList> getListData() {return listData;}public void setListData(ArrayList> listData) {this.listData = listData;}@Overridepublic int describeContents() {return 0;}//进行序列化存储@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(id);dest.writeString(name);dest.writeInt(age);dest.writeParcelable(sonInfo, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);dest.writeStringArray(boyfriendAry);dest.writeList(listData);}public static final Parcelable.Creator CREATOR = new Creator() { @Override public UserInfo[] newArray(int size) { return new UserInfo[size]; } //将Parcel对象反序列化为UserInfo @Override public UserInfo createFromParcel(Parcel source) { return new UserInfo(source); } }; }
同样SonInfo类也要实现Parcelable接口:
[java] view plaincopyprint?- package com.demo.entity;
- import android.os.Parcel;
- import android.os.Parcelable;
- public class SonInfo implements Parcelable{
- private String id;
- private String name;
- public SonInfo(){
- }
- public SonInfo(String id,String name){
- this.id = id;
- this.name = name;
- }
- public SonInfo(Parcel source){
- this.id = source.readString();
- this.name = source.readString();
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(id);
- dest.writeString(name);
- }
- public static final Parcelable.Creator
CREATOR = new Creator () { - @Override
- public SonInfo[] newArray(int size) {
- return new SonInfo[size];
- }
- //将Parcel对象反序列化为UserInfo
- @Override
- public SonInfo createFromParcel(Parcel source) {
- return new SonInfo(source);
- }
- };
- }
package com.demo.entity;import android.os.Parcel;import android.os.Parcelable;public class SonInfo implements Parcelable{private String id;private String name;public SonInfo(){}public SonInfo(String id,String name){this.id = id;this.name = name;}public SonInfo(Parcel source){this.id = source.readString();this.name = source.readString();}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(id);dest.writeString(name);}public static final Parcelable.Creator CREATOR = new Creator() { @Override public SonInfo[] newArray(int size) { return new SonInfo[size]; } //将Parcel对象反序列化为UserInfo @Override public SonInfo createFromParcel(Parcel source) { return new SonInfo(source); } }; }
下面来看一下测试类:
MainActivity类,在这里面进行数据的封装,然后传递到StubActivity类中:
[java] view plaincopyprint?- package com.demo.parcel;
- import java.util.ArrayList;
- import java.util.HashMap;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import com.demo.entity.SonInfo;
- import com.demo.entity.UserInfo;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Intent intent = new Intent(this,StubActivity.class);
- ArrayList
> listData = new ArrayList >(); - HashMap
tempMap = new HashMap (); - tempMap.put("one_child", new SonInfo("001_1","jiangwei_one_child"));
- listData.add(tempMap);
- UserInfo userInfo = new UserInfo("001","jiangwei",24,new String[]{"张三","李四","王五"},listData);
- SonInfo sonInfo = new SonInfo();
- sonInfo.setId("001_1");
- sonInfo.setName("jiangwei_child");
- userInfo.setSonInfo(sonInfo);
- intent.putExtra("userinfo", userInfo);
- startActivity(intent);
- }
- }
package com.demo.parcel;import java.util.ArrayList;import java.util.HashMap;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import com.demo.entity.SonInfo;import com.demo.entity.UserInfo;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this,StubActivity.class);ArrayList> listData = new ArrayList>();HashMap tempMap = new HashMap();tempMap.put("one_child", new SonInfo("001_1","jiangwei_one_child"));listData.add(tempMap);UserInfo userInfo = new UserInfo("001","jiangwei",24,new String[]{"张三","李四","王五"},listData);SonInfo sonInfo = new SonInfo();sonInfo.setId("001_1");sonInfo.setName("jiangwei_child");userInfo.setSonInfo(sonInfo);intent.putExtra("userinfo", userInfo);startActivity(intent);}}
下面就是StubActivity类,在这个类中将读出数据进行显示: [java] view plaincopyprint?
- package com.demo.parcel;
- import java.util.ArrayList;
- import java.util.HashMap;
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- import com.demo.entity.SonInfo;
- import com.demo.entity.UserInfo;
- public class StubActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_stub);
- UserInfo userInfo = (UserInfo)this.getIntent().getParcelableExtra("userinfo");
- SonInfo sonInfo = userInfo.getSonInfo();
- String[] boyfriend = userInfo.getBoyfriendAry();
- for(int i=0;i
- Log.e("boyfriend_name:",boyfriend[i]);
- }
- ArrayList
> listData = userInfo.getListData(); - for(int j=0;j
- SonInfo temp_soninfo = listData.get(j).get("one_child");
- Log.e("OneChildId:",temp_soninfo.getId()+"");
- Log.e("OneChildName:",temp_soninfo.getName()+"");
- }
- Log.e("UserId:",userInfo.getId()+"");
- Log.e("UserName:",userInfo.getName()+"");
- Log.e("UserAge:",userInfo.getAge()+"");
- Log.e("Son_id:",sonInfo.getId()+"");
- Log.e("Son_name:",sonInfo.getName()+"");
- }
- }
package com.demo.parcel;import java.util.ArrayList;import java.util.HashMap;import android.app.Activity;import android.os.Bundle;import android.util.Log;import com.demo.entity.SonInfo;import com.demo.entity.UserInfo;public class StubActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_stub);UserInfo userInfo = (UserInfo)this.getIntent().getParcelableExtra("userinfo");SonInfo sonInfo = userInfo.getSonInfo();String[] boyfriend = userInfo.getBoyfriendAry();for(int i=0;i> listData = userInfo.getListData();for(int j=0;j
运行结果:
这样就成功了使用了Parcelable进行数据的传输。
更多相关文章
- SSH服务器与Android通信(3)--Android客户端发送数据
- android多线程访问服务器数据
- Android(安卓)P解决Socket通信Tcp粘包问题
- Service与Android系统设计(3)
- android学习笔记之十二进程通信(IPC)
- android ListView 中getview学习总结
- android 访问 OData
- Android(安卓)性能优化之使用MAT分析内存泄露问题
- 20172321 2017-2018-2 《程序设计与数据结构》第11周学习总结