一句话描述
将对象序列化到文件,然后从文件中反序列化出对象是一个常见的场景。常见的有json序列化,但是json 反序列化使用反射,性能较差,所以在此我们使用 Android 中Parcel 进行本地序列化并保存到文件,并从文件中读取并反序列化。
序列化并保存到文件
- 创建一个类,并让它实现 Parcelable 接口。
- 在类中重写 writeToParcel() 方法,将对象的成员变量写入到 Parcel 中,需要注意顺序和类型。
- 在类中创建一个名为 CREATOR 的静态常量,该常量实现了 Parcelable.Creator 接口,并重写了其中的 createFromParcel() 和 newArray() 方法。
- 创建一个 FileOutputStream 对象,指定保存的文件路径。
- 创建一个 Parcel 对象,并调用 writeToParcel() 方法将数据写入到 Parcel 中。
- 调用 Parcel 的 marshall() 方法将 Parcel 数据转换成字节数组,然后将其写入到文件中。
示例代码:
// 创建 Person 类,并实现 Parcelable 接口
public class Person implements Parcelable {...}
// 保存对象到文件
public void saveParcelableToFile(Person person, String filePath) {
// 创建 FileOutputStream 对象
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filePath);
// 创建 Parcel 对象
Parcel parcel = Parcel.obtain();
person.writeToParcel(parcel, 0);
// 将 Parcel 数据转换成字节数组,并写入到文件中
byte[] data = parcel.marshall();
fos.write(data);
parcel.recycle();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
从文件中反序列化
- 创建一个 FileInputStream 对象,指定要读取的文件路径。
- 创建一个 byte[] 数组,用来存储从文件中读取到的数据。
- 将文件中的数据读取到 byte[] 数组中,并创建一个 Parcel 对象。
- 调用 Parcel 的 unmarshall() 方法将字节数组转换成 Parcel 数据。
- 调用 Parcel 的 setDataPosition(0) 方法,重置 Parcel 数据读取位置。
- 调用 CREATOR.createFromParcel(parcel) 方法,从 Parcel 中反序列化出对象。
示例代码:
// 从文件中读取对象并反序列化
public Person readParcelableFromFile(String filePath) {
// 创建 FileInputStream 对象
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
// 从文件中读取数据到 byte[] 数组中
byte[] data = new byte[fis.available()];
fis.read(data);
// 创建 Parcel 对象,并将 byte[] 数组转换成 Parcel 数据
Parcel parcel = Parcel.obtain();
parcel.unmarshall(data, 0, data.length);
parcel.setDataPosition(0);
// 从 Parcel 中反序列化出对象
Person person = Person.CREATOR.createFromParcel(parcel);
parcel.recycle();
return person;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
小结
这样就可以通过序列化并保存到文件,然后从文件中读取并反序列化对象了。需要注意的是,在调用 Parcel.marshall() 方法和 Parcel.unmarshall() 方法时,需要保证两次调用之间数据的顺序和类型一致。