登录

去注册

登录

注册

去登录

注册

每日一问 Parcelable 为什么效率高于 Serializable ?

xiaoyang   2019-08-26   收藏

  1. 为什么效果比Serializable高?
  2. 为了效率损失了什么?
  3. 一个对象可以序列化的关键,你认为是?
12
1、为什么Parcelable的效率比Serializable高?

可以从设计目的和实现原理两个方面分析
1)设计目的
Serializable是Java API,是一个通用的序列化机制,通过将文件保存到本地文件、网络流等实现便数据的传递,这种数据传递不仅可以在单个程序中进行,也可以在两个不同的程序中进行;Parcelable是Android SDK API,为了在同个程序的不同组件之间和不同程序(AIDL)之间高效的传输数据,是通过IBinder通信的消息的载体。从设计目的上可以看出Parcelable就是为了Android高效传输数据而生的。
2)实现原理
Serializable是通过I/O读写存储在磁盘上的,使用反射机制,序列化过程较慢,且在序列化过程中创建许多临时对象,容易触发GC。Parcelable是直接在内存中读写的,自已实现封送和解封(marshalled &unmarshalled)操作,将一个完整的对象分解成Intent所支持的数据类型,不需要使用反射,所以Parcelable具有效率高,内存开销小的优点。

2、Parcelable为了效率损失了什么

Serializable是通用的序列化机制的,将数据存储在磁盘,可以做到有限持久化保存,文件的生命周期不受程序影响,Parcelable的序列化操作完全由底层实现,不同版本的Android是实现方式可能不相同,所以不能进行持久化存储。

3、一个对象可以序列化的关键

序列化是将一个对象从存储态转化成传输态的过程,把对象转化成字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
在序列化时,对象的各属性都必须是可序列化的,声明为static和transient类型的成员数据不能被序列化。
并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如:
1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
2.资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。

回复
7

大家的回答都好棒~ d(* ̄▽ ̄)===b ,我就说说源码大致实现好了:

看了下源码,发现操作SerializableObject(Input,Output)Stream,都是直接在java层实现,而Parcel的主要逻辑都是通过native方法实现的。

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来保存。

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

回复
6

俩者都是序列化接口
Parcelable(安卓)特点:高效但复杂,将一个对象进行分解,且分解的每一部分都是可支持可传递的数据类型
Serializable (Java)特点:开销大效率低但简单,主要是将一个对象转换成可存储可传输的状态

对于Intent等内存中传递数据建议用Parcelable进行序列化,对于需要将数据保存到本地或网络传输建议用Serializable

回复
2

说Serializable需要磁盘IO的 请看这篇博客(Android 面试(七):Serializable 这么牛逼,Parcelable 要你何用?)已经对其加了删除线.

回复
1
  1. S是基于Java实现的,内部会频繁gc,进而内存开销大,可以进行网络传输本地存储,而P是基于android的,只能内存间传输。
  2. P为了内存间传输效率减少了它的能力,无法网络传输,无法本地存储。
  3. 可拆分,可见性(我猜。。。)
回复
1

回答 第1,2的问题:

Parcelable: 拿空间换时间,
Serializable :拿时间换空间
注:这里的"换",针对内存的说法

回复
0

根据小缘的源码指导,撸了一遍源码来回答

  1. 效率
    Serializable 内部序列化的时侯没有使用反射,但是反序列化中使用了反射,所以导致 Serializable 的效率比 Parcelable 低。
    Parcelable 使用内存拷贝,效率比 Serializable 高。
  2. 损失
    Serializable 是 Java 平台通用的序列化接口,可用于磁盘存储就行持久化操作。
    Parcelable 是在Android SDK 中,受版本影响较大,且难以就行数据持久化。
  3. 关键
    对象的属性都能进行序列化。
回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定