您的位置:首页 > 移动开发 > Android开发

持久化保存Parcelable实践

2016-05-03 00:17 471 查看
最近突发奇想,希望持久化保存Activity的信息,做应用恢复使用,而在Activity中最基本的Intent,Bundle都是基于Parcelable的,于是就研究了下Parcelable的持久化。

查阅了很多资料,无一例外的都有这样一段话(当然都是拿来主义)

Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化


Parcelable既然可以序列化,那么也就是Parcelable里面的数据按照一定的规则用字节流存起来了,既然如此,我们只要能够从Parcel中获取到字节流,其实也就完成了持久化Parcelable的工作了。

详细看了一下Parcel的代码,Android Studio确实方便,直接看反编译出来的文件(其实Android Studio已经对SDK的源码做了关联),Parcel中的unmarshall和marshall两个方法引起了我的注意,一个拿到字节数组,一个存入字节数组,完全就是我想要的嘛。

那么就做个demo试验一下,试验的思路如下:

准备一个实现Parcelable接口的类

准备DiskLruCache

写方法,把需要保存的数据通过Parcel序列化保存,拿到字节数组,存DiskLruCache

读方法,从DiskLruCache中读字节数组,然后放到Parcel里,在从Parcel中反序列化读出

编码

序列化的类

private static class TestParcel implements Parcelable{

private String name;

public TestParcel(String name) {
this.name = name;
}

protected TestParcel(Parcel in) {
this.name=in.readString();
}

public static final Creator<TestParcel> CREATOR = new Creator<TestParcel>() {
@Override public TestParcel createFromParcel(Parcel in) {
return new TestParcel(in);
}

@Override public TestParcel[] newArray(int size) {
return new TestParcel[size];
}
};

@Override public int describeContents() {
return 0;
}

@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}


读方法和写方法

@TargetApi(Build.VERSION_CODES.FROYO) protected void load(){
File file = getExternalCacheDir();
if(!file.exists()){
file.mkdirs();
}
try {
cache=DiskLruCache.open(file,0,1,10*1024*1024);
DiskLruCache.Snapshot snapshot= null;
snapshot = cache.get("123456");

InputStream inputStream = snapshot.getInputStream(0);
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
Parcel parcel = Parcel.obtain();
parcel.unmarshall(bytes,0,bytes.length);
parcel.setDataPosition(0);
int size = parcel.readInt();
List<TestParcel> list = new ArrayList<>(size);
parcel.readTypedList(list,TestParcel.CREATOR);
inputStream.close();
snapshot.close();
//cache.close();
} catch (IOException e) {
e.printStackTrace();
}
}

@TargetApi(Build.VERSION_CODES.FROYO) protected void save(){
File file = getExternalCacheDir();
if(!file.exists()){
file.mkdirs();
}
try {
cache=DiskLruCache.open(file,0,1,10*1024*1024);
DiskLruCache.Editor editor = cache.edit("123456");
OutputStream outputStream = editor.newOutputStream(0);
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
Parcel parcel = Parcel.obtain();
List<TestParcel> list = new ArrayList<>();
for(int i = 0;i<10;i++){
list.add(new TestParcel("hello"+i));
}
parcel.writeInt(list.size());
parcel.writeTypedList(list);

bos.write(parcel.marshall());
bos.flush();
bos.close();
outputStream.flush();
outputStream.close();
editor.commit();
cache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}


然后就是run了,数据顺利的保存,然后读取,只是在Parcel反序列化时有一点小挫折,原因就是,unmarshall之后要把Parcel的dataPosition重置,不然什么数据也读不到,这也是踩过坑才得出来的建议。

之后就完全与序列化时存入的数据一致了。

经过一番折腾,证明这思路是可行的。

如此看来,Parcelable持久化并不是不可行,只是适用场景的区别罢了。

通过这次尝试也加深的对Android序列化的理解,也是一次值得的实践。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息