andorid序列化总结

网上其实有很多博客和论坛都解释了序列化是什么,但是看完解释还是很懵逼,可能是境界还不够吧。无奈.png

这个序列化到底是什么?我为什么要用它?用它有什么好处?什么情况下用它?一脸懵逼.jpg
我收集了一些资料,这里做个总结:

1.序列化到底是什么?

百度百科的解释是:对象的状态信息转换为可以存储或传输的形式的过程
android中主要存在2种序列化方法:Parcelable 和 Serializable

  • Serializable
    将对象信息转换为字节流、文件或数据库等形式来存储(反序列化就是反过程)
  • Parcelable
    将对象信息进行一次选择性的深拷贝,拷贝的对象存放在内存中(反序列化就是再复制拷贝对象)

Serializable 通过反射将信息存在磁盘中(转为字节流除外),即使程序再次启动也能找回数据
Parcelable 将信息存在内存中,程序再次启动之前拷贝的数据就消失了

2.我为什么要用它?

这里举个例子: Activity A 传递一个对象user 给 Activity B
user 是A中的一个局部变量,在B中无法直接访问,这时候系统提供2种方法:Bundle.putSerializable(Key,Object)和Bundle.putParcelable(Key,Object)

疑问一, 为什么我不用静态对象User,这样直接在B上获取对象

静态对象是个好主意,可是当我在B上修改了user,其他地方使用的user也会发生变化,这就可能存在问题(Parcelable其实也算静态对象的方案,只是更巧妙些)

疑问二, 为什么我不直接将User转化为json(xml/protobuf等)格式,再通过String(Byte等)格式传递?

json是一个很好的解决方案,在效率上会优于Serializable(Serializable可以存储在磁盘),但低于Parcelable(Parcelable占内存)。各有优缺点吧

疑问三,为什么我不使用sp存储User对象,然后在B中还原?

sp可以存储轻量级的数据,而且可以解决intent 传递数据大小限制(binder缓冲池大小限制(有些手机为2M)),缺点是sp不支持跨app进程使用。
数据少这么操作麻烦,数据多的话就挺好的(FileProvider存储文件也和这个一样的效果)
至于说用上数据库或者先传到网上,然后再下载下来,就有些大炮打蚊子了。

疑问四,为什么我不使用handler或rxBus等骚操作来做?

并没有阻止你用,骚操作要用的骚才行(只是这2种方式使用更简单些)

3. 用它有什么好处?

固有思维: 数据持久化

4. 什么情况下用它?

进程间通信用的比较多(基本和binder有关)

5.扫盲

是否实现了对应的接口就实现了序列化

错误

  • Serializable
public class Person implements Serializable{
    //建议自己定义,不要用系统自动生成的
    private static final long serialVersionUID = 1L;
    private String name;

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

//储存
Person p = new Person("张三");
//不只是能使用FileOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/person.txt")));
oos.writeObject(flyPig);
oos.close();
//获取
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/person.txt")));
Person p2  = (Person) ois.readObject();
  • Parcelable
//person
public class Person implements Parcelable {
    private String name;

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

    public Person(Parcel in) {
        name = in.readString();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }
}
//存储
Person p = new Person("张三");
Parcel parcel = Parcel.obtain();
p.writeToParcel(parcel,0);

//获取
Parcel parcel = Parcel.obtain();
Person p2 = Person.CREATOR.createFromParcel(parcel);

android源码其实很多地方都已经运用了序列化

//String 
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence { ... }

//number
public abstract class Number implements java.io.Serializable { ... }

//file
public class File
    implements Serializable, Comparable<File> { ... }

public final class Bitmap implements Parcelable { ... }

父类实现了接口,子类是否可以序列化

  • Serializable
    子类可以序列化
    如果想要序列化一个类,必须要实现Serializable接口,包括他的属性
    子类只可以序列化父类的可见属性,例如public,protected,或者其他情况,并且必须提供一个无参构造方法,否则会在运行时报错
  • Parcelable
    子类只可以序列化父类的属性,不可以序列化自己的属性,除非重写createFromParcel和writeToParcel方法

源码流程简析

这里copy下大佬的分析吧(具体源码分析可以去看下面推荐的文章,反正这个文字描述源码流程我不想写了╮(╯▽╰)╭):

Serializable原理:

writeObject方法流程大致如下:

  1. 借助ObjectStreamClass记录目标对象的类型类名等信息,这个类里面还有个ObjectStreamField数组,用来记录目标对象的内部变量;

  2. defaultWriteFields方法中,会先通过ObjectStreamClassgetPrimFieldValues方法,把基本数据类型的值都复制到一个叫primVals的byte数组上;

  3. 接着通过getPrimFieldValues方法来获取所有成员变量的值,出乎意料的是:这两个获取值的方法,里面都不是我们常规的反射操作(Field.get),而是通过操作Unsafe类来完成的

  4. 遍历剩下不是基本数据类型的成员变量,然后递归调用writeObject方法(也就是一层层地剥开目标对象,直到找到基本数据类型为止);

readObject流程差不多:先通过readClassDescriptor方法(里面会把InputStream里面的数据读出来)获取到ObjectStreamClass 的实例,再根据这个实例来把基本数据类型引用数据类型分别赋值到用反射创建的目标对象实例中

Parcel原理:

它的各种writeXXX方法,在native层都是会调用Parcel.cpp的write方法,它是直接复制内存( memcpy),地址由一个叫mDatauint8_t来保存,mDataCapacity来表示parcel缓存容量(大小),mDataPos指向parcel缓存中空闲区域的首地址(有偏移量)

read方法同理,它也是通过 memcpy函数来把mData上的某部分数据复制出来。

6. 总结

Serializable 反射多性能低,但存储磁盘,能持久保存
Parcelable 性能更高,但占内存,无法持久保存


7. 相关文章推荐

  1. 每日一问 Parcelable 为什么效率高于 Serializable ?
  2. Serializable 这么牛逼,Parcelable 要你何用?
  3. Java 序列化和反序列化(二)Serializable 源码分析 - 1
  4. Parcelable最强解析
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容

  • Android数据序列化总结 目录介绍 1.序列化简单介绍1.1 序列化的概念1.2 序列化是做什么用的1.3 序...
    杨充211阅读 1,075评论 0 5
  • 段子 公园里,一位仙风鹤骨的老者在打太极,一招一式都仙气十足,一个年轻人走过去:“大爷,太极这玩意儿花拳绣腿,你练...
    大公爵阅读 17,818评论 4 41
  • JAVA序列化机制的深入研究 对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整...
    时待吾阅读 10,872评论 0 24
  • 3. IPC机制(基础) 3.0 前言 本文总结自任玉刚老师的《Android开发艺术探索》,文章中的【示例】在这...
    Entschuldigung_阅读 637评论 0 1
  • 从今天起想做一个阳光一点的人 我知道我脾气不好 说话不过脑子 但我愿意试着去改 我知道我爱多想乱想 我也想阳光一点...
    岛屿始终在海里阅读 163评论 0 0