一、Android 中常用的序列化
Parcelable
- 1、占内存小,由于没有字段特点、编码等额定信息
- 2、在 Android IPC 中序列化和反序列化速度快
- 3、存储数据以根本数据类型为单元,一切数据运用根本类型存储,引证类型存储(除 String)之外,会存储类名,字符类型会供给长度符号
- 序列化和反序列化进程复杂,手动完结读和写,还需要凭借Parcel,必要时设置ClassLoader
Serializable
- 数据可读性好相对较好
- 存储目标数据时会保存字段名和字段类型
- 占用内存空间大
- 序列化反序列化比较耗时,相比 Parcelable 只经过反射 new 目标,Serializable 字段反射也很频繁
- 序列化和反序列化进程简单,根本调用api就完结
二、序列化巨细测验
定义一个类,一起支撑 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;
}
public int describeContents() {
return 0;
}
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];
}
};
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");
//Parcelable序列化
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();
aRaf.write(baos.toByteArray());
// Serializable 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(baos);
outputStream.writeUTF("Aa");
outputStream.writeInt(2);
outputStream.writeObject(aRect);
bRaf.write(baos.toByteArray());
outputStream.close();
aRaf.close();
bRaf.close();
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);
Serilizable 反序列化
这种办法很老练,本篇就贴出来了。
作用
Parcelable序列化后的文件编码
Serializable序列化后的文件编码
存储特色:
- 【1】Parcelable 依靠次序,数据分为 “字符类型” + “byte 类型”, 而 Serializable 根本上会保存字段名,字段类型,乃至 utf 编码
- 【2】Parcelable 中字符串类名最终都会以 char 类型存储,存储 String 或 Char 类型时会在最初往前推,第四个字节时字符串或 Char 的长度
- 【3】Parcelable 数据包中,如果最终一位时字符类型,那么会在后边00 00 00后边在添加FF FF FF,以此表明数据包结束。(这句本来是测过,懒得发图了)
可见,跟着字段的增多,Parcelable 优势将更加明显
性能测验
其实从数据I/O和反射次数就能明显的看出Parcelable更胜一筹,这里就不测验了。
RPC、IPC、耐久化
Serializable、protobuf 经常被用于RPC和耐久化存储,而Parcelable由于能够减少数据量,特别适合跨进程通讯,无论是Binder、LocalSocket还是ShareMemory都能运用Parcelable跨进程数据传输(IPC)。
Parcelable 耐久化问题
对于Parcelable是不是支撑耐久化问题,很多博客说“不能”耐久化,其实本篇能够看到其自身是支撑耐久化的,显然“不能”这个表述是不恰当的。
那究竟应不应该运用Parcelable耐久化呢?
作为运用过Parcelable耐久化方法的开发者,我的总结如下:
- 正常情况下是能够运用Parcelable进行耐久化的,但是要避免字段类型、读写次序改变
- Parcelable耐久化不支撑字段特点(字段类型、字段称号)记忆,因而,康复方法只能依靠Android渠道
- Parcelable不支撑字段裁剪,如果你想删去某个之前的字段,可能会导致反序列化失利。
- Parcelable短少版本机制,因而需要自行记录和设置更新机制
- 和Serializable相同,不适合频繁I/O
总结
本篇咱们经过手动实践,对咱们常见的数据目标进行比较体系的知道,Parcelable不只性能上更优异,其次也能够支撑耐久化,不过建议存储一些数据量较大(如配置项)、字段不会裁剪、类型不会变化的数据。