在Android中有两种接口可以实现序列化操作:Serializable和Parcelable。前者是Java API中带的,后者则是Android API中的。我们一次来学习一下。

Serializable接口

利用这个接口是实现序列化很简单,只需在相应的类中实现这个接口即可,而且不用实现任何方法,如下

public class Item implements Serializable{    public int id;    public String msg;    Item(int id,String msg){        this.id = id;        this.msg = msg;    }}

用法很简单,但有一点需要注意,我们在看这个接口介绍时需要有一个serialVersionUID,或者我们看源码时,有些实现了该接口的类都有这个ID,如ArrayList:

public class ArrayList extends AbstractList        implements List, RandomAccess, Cloneable, java.io.Serializable{    private static final long serialVersionUID = 8683452581122892189L;    ...}

但用过的朋友可能会发现,不写这个UID也能正常实现序列化和反序列话,那么这个UID有什么用呢?这里有一点需要注意的是,如果我们不写这个UID,是不是真的就没有呢,事实上,如果不写编译器会自动根据类的内容计算一个hash值,作为这个类的UID。那么这个值又有什么用呢?既然是ID肯定是作为一个标识符,只要标识符一样,我们在反序列的时候即使类有改变,也能尽可能的还原数据,示例如下:

我们先手动指定一个UID

public class Item implements Serializable{    public static final long serialVersionUID = 1L;    public int id;    public String msg;    Item(int id,String msg){        this.id = id;        this.msg = msg;    }}

在执行序列化操作:

       try {            File file = new File(getFilesDir(),"Serializable");            if (file.exists())                file.delete();            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));            out.writeObject(new Item(10,"a"));            out.close();        } catch (IOException e) {            e.printStackTrace();        }

此时我们如果不做更改,直接反序列化,肯定是可以的。但是我们现在对Item类添加一个成员变量,但不改变其UID:

public class Item implements Serializable{    public static final long serialVersionUID = 1L;    public int id;    public String msg;    public String msg2;    Item(int id,String msg,String msg2){        this.id = id;        this.msg = msg;        this.msg2 = msg2;    }}

此时在再执行反序列化操作,如下

       try {            ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(getFilesDir(),"Serializable")));            Item item = (Item) in.readObject();            in.close();            Toast.makeText(this,item.id+item.msg,Toast.LENGTH_SHORT).show();        } catch (Exception e) {            Toast.makeText(this,e.getMessage(),Toast.LENGTH_SHORT).show();        }

发现是可以正确解析到数据的,此时如果我们删掉那个手动指定的UID会如何呢?结果会出现下面异常:



大致意思就是序列化文件里的UID为1,而本地类的UID变成了这么一长串数字,可见我们即使不写这个ID,编译器也会给我们加上,一旦类发生改变,ID就会改变,导致反序列化失败,若是UID相同,即使类有改变,也会尽可能的恢复数据。但是并不是所有情况都可以,比如类名的改变,自然是不可能恢复的

Parcelable接口

相比Serializable,这个接口就复杂的多了,一个简单的例子如下:

public class Item implements Parcelable{    public int id;    public String msg;    Item(int id,String msg){        this.id = id;        this.msg = msg;    }    protected Item(Parcel in) {        id = in.readInt();        msg = in.readString();    }    public static final Creator CREATOR = new Creator() {        @Override        public Item createFromParcel(Parcel in) {            return new Item(in);        }        @Override        public Item[] newArray(int size) {            return new Item[size];        }    };    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(id);        dest.writeString(msg);    }}

对比得知,Serializable的序列化方式并不指明具体的实现方式,而Parcelable则根据具体的方法来实现,比较清晰。如序列化过程由writeToParcel完成,其实就是将各个数据写到一个Parcel对象里,反序列化由一个静态的Creator实例化对象完成,调用其中的createFromParcel方法即可。虽然要实现的方法比较复杂,但是如果你使用的是Android Studio,其中的代码智能补全可以帮你把所有事情都完成。下面我问就写一个例子,应用一下。

Intent intent = new Intent();intent.putExtra("item",new Item(10,"s"));intent.setClass(getApplicationContext(),SecondActivity.class);startActivity(intent);
Item item = getIntent().getParcelableExtra("item");Toast.makeText(this,item.id+item.msg,Toast.LENGTH_SHORT).show();

还有一点我们要清楚,Parcelable是Android里面的,所以不能用于IO序列化对象,但能用在Intent传递数据或其他方面。另外Parcelable中还有一个describeContents方法,这个方法在含有文件描述符时应该返回1,其余几乎所有情况都返回0.

两种序列化的比较

一般而言,Serializable时借助IO的,需要大量IO操作,比较消耗性能,Parcelable都是在内存中完成的,效率比较高。但是Parcelable不能进行数据持久化,这时还需要Serializable

更多相关文章

  1. Android(安卓)AOP之AspectJ入门
  2. Android(安卓)DataBinding使用详解(一)
  3. android 【点击输入框调出输入法前的】输入框获取焦点和输入法的
  4. 使用 SQLiteDatabase 操作 SQLite 数据库
  5. 转:ANDROID音频系统散记之四:4.0音频系统HAL初探
  6. Android(安卓)studio 中与本地 html 页面交互
  7. Android(安卓)开发者必知必会的权限管理知识
  8. 真机上使用Hierarchy Viewer
  9. Android(安卓)studio 命令gradlew assembleRelease打包时,出现 Un

随机推荐

  1. ACCESS中Dlookup函数使用
  2. 95.自动挂载云盘
  3. 从IIC实测波形入手,搞懂IIC通信
  4. RGB-LCD液晶屏层叠显示测试
  5. 嵌入式开发,各类存储方式知多少?
  6. Bootstrap 学习 - 网格系统
  7. MPU6050姿态解算2-欧拉角&旋转矩阵
  8. FreeRTOS例程4-串口DMA收发不定长数据
  9. 欧拉角旋转
  10. FreeRTOS例程3-串口中断接收不定长的数据