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?
  1. publicclass MyParcelable implements Parcelable {
  2. privateint mData;
  3. private String mStr;
  4. publicint describeContents() {
  5. return 0;
  6. }
  7. // 写数据进行保存
  8. publicvoid writeToParcel(Parcel out, int flags) {
  9. out.writeInt(mData);
  10. out.writeString(mStr);
  11. }
  12. // 用来创建自定义的Parcelable的对象
  13. publicstatic final Parcelable.Creator CREATOR
  14. = new Parcelable.Creator() {
  15. public MyParcelable createFromParcel(Parcel in) {
  16. return new MyParcelable(in);
  17. }
  18. public MyParcelable[] newArray(int size) {
  19. return new MyParcelable[size];
  20. }
  21. };
  22. // 读数据进行恢复
  23. private MyParcelable(Parcel in) {
  24. mData = in.readInt();
  25. mStr = in.readString();
  26. }
  27. }
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?
  1. package com.demo.entity;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import android.os.Parcel;
  5. import android.os.Parcelable;
  6. /**
  7. * 用户信息,实现Parcelable接口
  8. * String,int,String[],ArrayList>这四种类型测试
  9. * @author weijiang204321
  10. *
  11. */
  12. public class UserInfo implements Parcelable{
  13. private String id;
  14. private String name;
  15. private int age;
  16. private String[] boyfriendAry = new String[3];
  17. private ArrayList> listData = new ArrayList>();
  18. private SonInfo sonInfo;
  19. public UserInfo(){
  20. }
  21. public UserInfo(String id,String name,int age,String[] boyfriendAry,ArrayList> listData){
  22. this.id = id;
  23. this.name = name;
  24. this.age = age;
  25. this.boyfriendAry = boyfriendAry;
  26. this.listData = listData;
  27. }
  28. public UserInfo(Parcel source){
  29. id = source.readString();
  30. name = source.readString();
  31. age = source.readInt();
  32. sonInfo = source.readParcelable(SonInfo.class.getClassLoader());
  33. source.readStringArray(boyfriendAry);
  34. source.readList(listData, SonInfo.class.getClassLoader());
  35. }
  36. public String getId() {
  37. return id;
  38. }
  39. public void setId(String id) {
  40. this.id = id;
  41. }
  42. public String getName() {
  43. return name;
  44. }
  45. public void setName(String name) {
  46. this.name = name;
  47. }
  48. public int getAge() {
  49. return age;
  50. }
  51. public void setAge(int age) {
  52. this.age = age;
  53. }
  54. public SonInfo getSonInfo(){
  55. return sonInfo;
  56. }
  57. public void setSonInfo(SonInfo sonInfo){
  58. this.sonInfo = sonInfo;
  59. }
  60. public String[] getBoyfriendAry() {
  61. return boyfriendAry;
  62. }
  63. public void setBoyfriendAry(String[] boyfriendAry) {
  64. this.boyfriendAry = boyfriendAry;
  65. }
  66. public ArrayList> getListData() {
  67. return listData;
  68. }
  69. public void setListData(ArrayList> listData) {
  70. this.listData = listData;
  71. }
  72. @Override
  73. public int describeContents() {
  74. return 0;
  75. }
  76. //进行序列化存储
  77. @Override
  78. public void writeToParcel(Parcel dest, int flags) {
  79. dest.writeString(id);
  80. dest.writeString(name);
  81. dest.writeInt(age);
  82. dest.writeParcelable(sonInfo, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  83. dest.writeStringArray(boyfriendAry);
  84. dest.writeList(listData);
  85. }
  86. public static final Parcelable.Creator CREATOR = new Creator() {
  87. @Override
  88. public UserInfo[] newArray(int size) {
  89. return new UserInfo[size];
  90. }
  91. //将Parcel对象反序列化为UserInfo
  92. @Override
  93. public UserInfo createFromParcel(Parcel source) {
  94. return new UserInfo(source);
  95. }
  96. };
  97. }
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);   
        }   
    };   

}


同样SonInfo类也要实现Parcelable接口:

[java] view plaincopyprint?
  1. package com.demo.entity;
  2. import android.os.Parcel;
  3. import android.os.Parcelable;
  4. public class SonInfo implements Parcelable{
  5. private String id;
  6. private String name;
  7. public SonInfo(){
  8. }
  9. public SonInfo(String id,String name){
  10. this.id = id;
  11. this.name = name;
  12. }
  13. public SonInfo(Parcel source){
  14. this.id = source.readString();
  15. this.name = source.readString();
  16. }
  17. public String getId() {
  18. return id;
  19. }
  20. public void setId(String id) {
  21. this.id = id;
  22. }
  23. public String getName() {
  24. return name;
  25. }
  26. public void setName(String name) {
  27. this.name = name;
  28. }
  29. @Override
  30. public int describeContents() {
  31. return 0;
  32. }
  33. @Override
  34. public void writeToParcel(Parcel dest, int flags) {
  35. dest.writeString(id);
  36. dest.writeString(name);
  37. }
  38. public static final Parcelable.Creator CREATOR = new Creator() {
  39. @Override
  40. public SonInfo[] newArray(int size) {
  41. return new SonInfo[size];
  42. }
  43. //将Parcel对象反序列化为UserInfo
  44. @Override
  45. public SonInfo createFromParcel(Parcel source) {
  46. return new SonInfo(source);
  47. }
  48. };
  49. }
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);   
        }   
    };   
	
}

下面来看一下测试类:

MainActivity类,在这里面进行数据的封装,然后传递到StubActivity类中:

[java] view plaincopyprint?
  1. package com.demo.parcel;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import android.app.Activity;
  5. import android.content.Intent;
  6. import android.os.Bundle;
  7. import com.demo.entity.SonInfo;
  8. import com.demo.entity.UserInfo;
  9. public class MainActivity extends Activity {
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. Intent intent = new Intent(this,StubActivity.class);
  15. ArrayList> listData = new ArrayList>();
  16. HashMap tempMap = new HashMap();
  17. tempMap.put("one_child", new SonInfo("001_1","jiangwei_one_child"));
  18. listData.add(tempMap);
  19. UserInfo userInfo = new UserInfo("001","jiangwei",24,new String[]{"张三","李四","王五"},listData);
  20. SonInfo sonInfo = new SonInfo();
  21. sonInfo.setId("001_1");
  22. sonInfo.setName("jiangwei_child");
  23. userInfo.setSonInfo(sonInfo);
  24. intent.putExtra("userinfo", userInfo);
  25. startActivity(intent);
  26. }
  27. }
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);
		
	}

}

下面就是StubActivity类,在这个类中将读出数据进行显示:

[java] view plaincopyprint?
  1. package com.demo.parcel;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import android.app.Activity;
  5. import android.os.Bundle;
  6. import android.util.Log;
  7. import com.demo.entity.SonInfo;
  8. import com.demo.entity.UserInfo;
  9. public class StubActivity extends Activity {
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_stub);
  14. UserInfo userInfo = (UserInfo)this.getIntent().getParcelableExtra("userinfo");
  15. SonInfo sonInfo = userInfo.getSonInfo();
  16. String[] boyfriend = userInfo.getBoyfriendAry();
  17. for(int i=0;i
  18. Log.e("boyfriend_name:",boyfriend[i]);
  19. }
  20. ArrayList> listData = userInfo.getListData();
  21. for(int j=0;j
  22. SonInfo temp_soninfo = listData.get(j).get("one_child");
  23. Log.e("OneChildId:",temp_soninfo.getId()+"");
  24. Log.e("OneChildName:",temp_soninfo.getName()+"");
  25. }
  26. Log.e("UserId:",userInfo.getId()+"");
  27. Log.e("UserName:",userInfo.getName()+"");
  28. Log.e("UserAge:",userInfo.getAge()+"");
  29. Log.e("Son_id:",sonInfo.getId()+"");
  30. Log.e("Son_name:",sonInfo.getName()+"");
  31. }
  32. }
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> listData = userInfo.getListData();
		for(int j=0;j
运行结果:

Android中的Serialable和Parcelable的区别_第1张图片

这样就成功了使用了Parcelable进行数据的传输。


你可能感兴趣的:(Android,UI)