热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[架构基础]Parcelable序列化详解与应用

在Android开发过程中,序列化是一个重要的概念,尤其是在数据传输和存储时。本文详细解析了Parcelable序列化的原理及其应用场景,并对比了其他序列化方式,如Serializable。通过具体的实例和代码示例,帮助开发者更好地理解和掌握Parcelable的使用方法,避免在实际开发和面试中遇到相关问题。

近来在使用Android序列化的时候遇到一些问题所以这里记录一下,一个不小心你面试就可能面上了。

什么时候使用序列化?

Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,在一般的时候推荐用这种方法提高性能。

###Parcelable和Serializable的区别

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable,除了以下介绍的坑问题。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

1.但是会有特殊的时候,例如以下代码有什么问题?

public class Person implements Parcelable {public String name;public int age;public List childlist;protected Person(Parcel in) {name = in.readString();age = in.readInt();childlist = in.createTypedArrayList(Person.CREATOR);}public static final Creator CREATOR = new Creator() {@Overridepublic Person createFromParcel(Parcel in) {return new Person(in);}@Overridepublic Person[] newArray(int size) {return new Person[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);dest.writeInt(age);dest.writeTypedList(childlist);}
}

估计一眼看不出有什么问题,问题就在于如果List childlist如果包含了当前的Person对象,序列化的时候,就会导致循环引用,一直序列化直到栈溢出,所以这里需要非常小心。有些时候为了代码抽象方便,很可能就会因此忽视了一些问题。

2.ParcelIn和writeToParcel的读和写的顺序需要是一致的,不然序列化会出错。

3.每次新加入属性,需要记得手动再次生成Parceble相应的方法。AS编译器生成是最稳的,别作死自己写。

4.抽象继承传递问题。 Person抽象类方法

public abstract class Person implements Parcelable {public String name;public int age;public List childlist;protected Person(Parcel in) {name = in.readString();age = in.readInt();childlist = in.createTypedArrayList(Person.CREATOR);job = in.readString();}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);dest.writeInt(age);dest.writeTypedList(childlist);dest.writeString(job);}@Overridepublic int describeContents() {return 0;}abstract String getJob();public static final Creator CREATOR = new Creator() {@Overridepublic Person createFromParcel(Parcel in) {return new Person(in) {@OverrideString getJob() {return "";}};}@Overridepublic Person[] newArray(int size) {return new Person[size];}};
}

Father实类

public class Father extends Person{public String job;protected Father(Parcel in) {super(in);}@OverrideString getJob() {return "soft engineer";}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {super.writeToParcel(dest,flags);}
}

这样一开始看没什么问题,可以正常传递。但是使用intent传递的时候,经过序列化后很有可能会数据丢失。因为抽象方法导致,某些数据序列化失败。

这种场景有两种解决方法

1.使用Serializable来序列化

2.将序列化操作移动到父类进行。

当然如果你有更好的写法可以联系我吧。

我建立了一个关于Android架构学习的群,里面可以进一步进行组件化学习和架构思想的的交流。

群号是316556016,也可以扫码进群。我在这里期待你们的加入!!!




推荐阅读
author-avatar
宫廷的围脖6uw_1911
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有