Anroid Parcelable与Serializable对象序列化比较

原创
03/15 08:56
阅读数 81

一、Android中常用的序列化

Parcelable

  • 1、占内存小
  • 2、在Android IPC中序列化和反序列化速度快
  • 3、存储数据以基本数据类型为单元,所有数据使用基本类型存储,引用类型存储(除String)之外,会存储类名,字符类型会提供长度标记

Serializable

  • 1、数据可读性好相对较好
  • 2、存储对象数据时会保留字段名和字段类型
  • 3、占用内存空间大
  • 4、序列化反序列化比较耗时,相比Parcelable只通过反射new对象,Serializable字段反射也很频繁

共性:

  • 都可以持久化存储
  • 都可以RPC传输

但google不太支持使用Parcelable做持久化和RPC传输,毕竟字段信息和类型信息存在缺失,如果不是独立模块开发,需要更多的协同。

 

二、序列化大小测试

定义一个类,同时支持Parcelable和Serializable


public class ARect implements Parcelable , Serializable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    private String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ARect r = (ARect) o;
        return left == r.left && top == r.top && right == r.right && bottom == r.bottom && TextUtils.equals(name,r.name);
    }

    @Override
    public int hashCode() {
        int result = left;
        result = 31 * result + top;
        result = 31 * result + right;
        result = 31 * result + bottom;
        result = result +name!=null?name.hashCode():0;
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(32);
        sb.append("Rect("); sb.append(left); sb.append(", ");
        sb.append(top); sb.append(" - "); sb.append(right);
        sb.append(", "); sb.append(bottom);
        sb.append(", "); sb.append(name);
        sb.append(")");
        return sb.toString();
    }


    /**
     * Parcelable interface methods
     */
    public int describeContents() {
        return 0;
    }

    /**
     * Write this rectangle to the specified parcel. To restore a rectangle from
     * a parcel, use readFromParcel()
     * @param out The parcel to write the rectangle's coordinates into
     */
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(left);
        out.writeInt(top);
        out.writeInt(right);
        out.writeInt(bottom);
        out.writeString(name);
    }

    public static final Parcelable.Creator<ARect> CREATOR = new Parcelable.Creator<ARect>() {
        /**
         * Return a new rectangle from the data in the specified parcel.
         */
        public ARect createFromParcel(Parcel in) {
            ARect r = new ARect();
            r.readFromParcel(in);
            return r;
        }

        /**
         * Return an array of rectangles of the specified size.
         */
        public ARect[] newArray(int size) {
            return new ARect[size];
        }
    };

    /**
     * Set the rectangle's coordinates from the data stored in the specified
     * parcel. To write a rectangle to a parcel, call writeToParcel().
     *
     * @param in The parcel to read the rectangle's coordinates from
     */
    public void readFromParcel(Parcel in) {
        left = in.readInt();
        top = in.readInt();
        right = in.readInt();
        bottom = in.readInt();
        name = in.readString();
    }

}

序列化

        ARect aRect = new ARect();
        aRect.left = 10;
        aRect.top = 10;
        aRect.bottom = 100;
        aRect.right = 100;
        aRect.name = "1H1";

        RandomAccessFile aRaf = new RandomAccessFile("/sdcard/arect_p.dat","rw");
        RandomAccessFile bRaf = new RandomAccessFile("/sdcard/arect_s.dat","rw");

        Parcel parcel = Parcel.obtain();
        parcel.setDataPosition(0);
        parcel.writeString("Aa");
        parcel.writeInt(2);
        parcel.writeParcelable(aRect, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        byte[] buf  = parcel.marshall();
        MappedByteBuffer mbb = aRaf.getChannel().map(FileChannel.MapMode.READ_WRITE,0,buf.length);
        mbb.put(buf);
        mbb.flip();

        ByteArrayOutputStream baos  = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(baos);
        outputStream.writeUTF("Aa");
        outputStream.writeInt(2);
        outputStream.writeObject(aRect);
        MappedByteBuffer bbb = bRaf.getChannel().map(FileChannel.MapMode.READ_WRITE,0,baos.size());
        bbb.put(baos.toByteArray());
        bbb.flip();
        outputStream.close();

        aRaf.close();
        bRaf.close();

大小对比

数据文件内容对比

存储特点:

  • 【1】Parcelable依赖顺序,数据分为“字符类型”+“byte类型”,而Serializable基本上会保留字段名,字段类型,甚至utf编码
  • 【2】Parcelable中字符串类名最终都会以char类型存储,存储String或Char类型时会在开头往前推,第四个字节时字符串或Char的长度
  • 【3】Parcelable数据包中,如果最后一位时字符类型,那么会在后面00 00 00 后面在添加 FF FF FF,以此表示数据包结束。(这句本来是测过,懒得发图了)

可见,随着字段的增多,Parcelable优势将更加明显

 三、性能测试

Parcelable存储格式短,读取顺序时强约束,占内存也很小,不需要查找数据类型和字符编码,其实都不用测试就能知道谁快谁慢。

Parcel dst = Parcel.obtain();
dst.unmarshall(buffer, 0, buffer.length);
dst.setDataPosition(0);
String Aa = dst.readString();
int b = dst.readInt();
ClassLoader classLoader = ARect.class.getClassLoader();
ARect dstRect = dst.readParcelable(classLoader);

这里给出Parcelable反序列化关键代码段,想测试的话也可以试试。

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部