Android中Serializable和Parcelable接口

  知人者智,自知者明。胜人者有力,自胜者强。——老子   

   最近在总结Activity之间数据传递的类型,我们都知道当Android中需要传递对象时一般要实现Serializable或Parcelable接口,但是只会写,对其一些内在的原理一点也不了解,阅读了多篇博客并亲自验证后,决定对Serializable和Parcelable的原理和使用做一个总结,如有谬误欢迎指正,如有疑问欢迎留言。我将在第一时间回答或改正。

  一、Serializable意思是序列化,什么是序列化与反序列化?
对象的序列化:把对象转换为字节序列的过程称为对象的序列化
反序列化:把字节序列恢复为Java对象的过程。
要想搞清楚序列化我们必须要清楚三点:Java对象、字节序列、存储。
①Java对象
Java对象包含变量与方法。但是序列与反序列化仅处理Java变量而不处理方法,序列与反序列化仅对数据进行处理。
②字节序列
其实就是连续排列的多个字符的序列,例如:“asdsdsfsdfsdff”
③存储
字符序列需要保存到一个地方,可以是硬盘也可以是内存。
简单说法是:序列化把当前对象信息保存下来。反序列化刚好相反的操作。
二、为什么要使用序列化?
在了解什么是序列化后可能会有人问为什么要使用序列化?它有什么用处?
从序列化的定义中我们可以看到它把一个对象转换成了流,并且将其保存到本地,那么我们就可以知道序列化主要有以下用途
(1)永久性保存对象,保存对象的字节序列到本地文件中;
(2)通过序列化对象在网络中传递对象;
(3)通过序列化在进程间传递对象(如:android通过序列化传递对象)。
、Java对象与Java对象序列化的区别?
      Java对象存在的前提必须在JVM运行期间存在,如果想在JVM非运行的情况下或者在其他机器JVM上获取指定Java对象,在现有Java对象的机制下都不可能完成。 
      与Java对象不同的是,如果对Java对象执行序列化操作,因为原理是把Java对象信息保存到存储媒介,所以可以在以上Java对象不可能存在的两种情况下依然可以使用Java对象。
四、如何实现序列化
Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。

注:Android中Intent传递对象有两种方法:一是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key,Object)。当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。
两种序列化方法的比较:
Serializable, 简单易用,效率低
serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。
这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。
Parcelable, 速度至上,代码量阅读和维护不易
根据Google工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。
关于 Parcelable比 Serializable运行快慢的比较详见此博客 http://greenrobot.me/devpost/android-parcelable-serializable/
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。从Parcelable设计的初衷中我们也能够看到Parcelable的速度是比较快的那么我们如何选择使用哪种序列化方式呢?
如果你想成为一个优秀的软件工程师,你需要多花点时间来实现Parcelable因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。
五、Parcelable 接口定义
public interface Parcelable
    {
        //内容描述接口,基本不用管
        public int describeContents();
        //写入接口函数,打包
        public void writeToParcel(Parcel dest, int flags);
        //读取接口,目的是要从Parcel中构造一个实现了 Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数<span style="white-space:pre">	</span>  传入<span style="white-space:pre">	</span>
        //为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例
        public interface Creator<T>
        {
               public T createFromParcel(Parcel source);
               public T[] newArray( int size);
        }
     }
六、应用举例
①实现Parcelable
实现Parcelable大致可以分为四个步骤:
1)implements Parcelable
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数    据到Parcel容器保存,以便从 Parcel容器获取数据
3)重写describeContents方法,内容接口描述,默认返回0就可以
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator
public static final Parcelable.Creator<T> CREATOR
注: 其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写 。需重写本接口中的两个方法:createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。
从Parcelable的实现步骤我们可以看到在此过程中: 通过writeToParcel将对象映射到Parceld对象,然后再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要我们来实现, 因此写的顺序和读的顺序必须一
创建一个实现了Parcelable接口的类
Book类
package com.example.progressbar;
import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {
     
private String name;     
private int price;
private String author;
     
public Book() {}
     
public Book(String name, int price, String author) {

     this.name = name;
     this.price = price;
     this.author = author;
}
     
public String getName() {
      return name;
 }
     
public void setName(String name) {

     this.name = name;
}
     
public int getPrice() {
     return price;
}
public void setPrice(int price) {

     this.price = price;
}
public String getAuthor() {
     return author;
}
    
public void setAuthor(String author) {
      this.author = author;
}
  @Override
public int describeContents() {
      return 0;
}
// 该方法将类的数据写入外部提供的Parcel中。
@Override
public void writeToParcel(Parcel parcel, int i) {
     parcel.writeString(this.name);
     parcel.writeInt(this.price);
     parcel.writeString(this.author);
}
  
public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {
// 返回一个Book[i]供外部类反序列化本类数组使用 
@Override
public Book[] newArray(int i) {        
     return new Book[i];
}
         
@Override       
public Book createFromParcel(Parcel parcel) {
// 将Parcel对象反序列化为Book对象
return new Book(parcel.readString(),parcel.readInt(),parcel.readString());
           }
     };
}
创建Student类实现Serializable,实现Serializable比较简单只需要implements  Serializable 即可。这只是给对象打了一个标记,系统会自动将其序列化。
Student类
packagecom.example.progressbar;
import java.io.Serializable;
publicclassStudent implements Serializable { 
private static final long serialVersionUID = 1L;
private String name;  
private int age;
private String sex;      
   public Student(){}
   public Student(String name,int age,String sex){          
       this.name=name;           
       this.age=age;          
       this.sex=sex;
}
  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 String getSex() {           
     return sex;
}
  public void setSex(String sex) {
      this.sex = sex;
   }
}
好了,这一篇博客就到这里了,看完了就留个言顶一个呗,您的支持是我前进的动力。






猜你喜欢

转载自blog.csdn.net/dmk877/article/details/48447783