- 为什么效果比Serializable高?
- 为了效率损失了什么?
- 一个对象可以序列化的关键,你认为是?
更多问答 >>
-
2019-09-01 23:16
-
2019-09-04 23:33
-
2019-09-09 00:19
-
2019-09-11 00:24
-
每日一问 gradle项目构建,需要经历哪些核心task,整个构建流程哪些我们可以干涉?
2019-09-15 23:29 -
每日一问 今天聊一下Gradle 相关,BuildConfig这个类是如何生成的?
2019-08-20 23:27 -
2019-08-18 21:42
-
每日一问 Android 有哪些 位运算 的例子很值得借鉴?
2019-08-13 21:56 -
2019-08-12 09:58
-
每日一问 事件分发机制大家应该都熟记于心,默认事件分发是逆序的,有哪些方法可以修改分发顺序?
2019-08-11 21:18

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类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。大家的回答都好棒~ d(* ̄▽ ̄)===b ,我就说说源码大致实现好了:
看了下源码,发现操作Serializable 的 Object(Input,Output)Stream,都是直接在java层实现,而Parcel的主要逻辑都是通过native方法实现的。
Serializable原理:
它的
writeObject方法流程大致如下:借助ObjectStreamClass记录目标对象的类型,类名等信息,这个类里面还有个ObjectStreamField数组,用来记录
目标对象的内部变量;在
defaultWriteFields方法中,会先通过ObjectStreamClass的getPrimFieldValues方法,把基本数据类型的值都复制到一个叫primVals的byte数组上;接着通过
getPrimFieldValues方法来获取所有成员变量的值,出乎意料的是:这两个获取值的方法,里面都不是我们常规的反射操作(Field.get),而是通过操作Unsafe类来完成的;遍历剩下不是基本数据类型的成员变量,然后递归调用
writeObject方法(也就是一层层地剥开目标对象,直到找到基本数据类型为止);readObject流程差不多:先通过readClassDescriptor方法(里面会把InputStream里面的数据读出来)获取到ObjectStreamClass 的实例,再根据这个实例来把基本数据类型和引用数据类型分别赋值到用反射创建的目标对象实例中。Parcel原理:
它的各种
writeXXX方法,在native层都是会调用Parcel.cpp的write方法(点蓝字可以看到对应的源码哦),它是直接复制内存( memcpy),地址由一个叫mData的uint8_t来保存。read方法同理,它也是通过 memcpy函数来把
mData上的某部分数据复制出来。偶遇小缘大佬,点个赞
有个问题,如果既要当api接口对象,又要存本地持久化,那改用哪种呢,暂时用的parcelable,感觉没什么影响
都可以,看需求,只是Parcelable不能直接写到文件中
厉害
Parcelable 可以写到文件中啊
俩者都是序列化接口
Parcelable(安卓)特点:高效但复杂,将一个对象进行分解,且分解的每一部分都是可支持可传递的数据类型Serializable (Java)特点:开销大效率低但简单,主要是将一个对象转换成可存储可传输的状态对于Intent等内存中传递数据建议用Parcelable进行序列化,对于需要将数据保存到本地或网络传输建议用Serializable
说Serializable需要磁盘IO的 请看这篇博客(Android 面试(七):Serializable 这么牛逼,Parcelable 要你何用?)已经对其加了删除线.
回答 第1,2的问题:
Parcelable: 拿空间换时间,
Serializable :拿时间换空间注:这里的"换",针对内存的说法一个是java实现,一个是native实现。
一个基于java IO可以做持久化存储,一个是基于内存直接操作。S应用范围更广,P主要应用Android ipc,效率更高。根据小缘的源码指导,撸了一遍源码来回答