导言
做Android开发的,相信大家都知道,Activity、Fragment之间的数据传递都是通过Bundle对象进行的。
而Bundle的Api中除了一些基本类型的方法之外,还有两个特殊的方法:
/**
* Inserts a Parcelable value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
* @param key a String, or null
* @param value a Parcelable object, or null
*/
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
* Inserts a Serializable value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
* @param key a String, or null
* @param value a Serializable object, or null
*/
@Override
public void putSerializable(@Nullable String key, @Nullable Serializable value) {
super.putSerializable(key, value);
}
那么,Serializable和Parcelable分别是什么呢?
Serializable
简介
Serialization是java自带的类型,做序列化用(把一个对象转换为可存储或可传输的形式的过程),对象可以将其当前状态存储到本地、数据库,也可以在网络上传输。以后,可以从存储区中读取或反序列化对象的状态,重新创建该对象。
序列化的本质是将运行时的对象转换为二进制流,保存到流、内存或通过网络传输。
实现方式
对象序列化很简单,只需要,实现Serialization类。
package com.bs.trade.main.bean;
import java.io.Serializable;
/**
* author : user_zf
* date : 18/3/17
* desc : 茶
*/
public class Tea implements Serializable {
private static final long serialVersionUID = -1241963366850216618L;
private String name;
private String price;
private String describe;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
看源码可以发现,Serialization是一个空的接口,它的作用是标志当前类可以被ObjectOutputStream序列化,和被ObjectInputStream反序列化。
可以看到需要定义一个serialVersionUID
变量,这个变量类似于接口版本号,标志了唯一一个可序列化的类。序列化过程会保存serialVersionUID
,反序列化过程会校验版本号是否一致,如果不一致,会报InvalidClassException
错误。
JVM规范强烈推荐手动声明一个版本号,AndroidStudio中可以设置Lint提示,自动生成版本号。如果不手动设置这个值,系统会生成一个默认hash值,一旦类结构发生改变,hash值对应改变,那么反序列化就会校验serialVersionUID
失败。设置了固定值,即使类结构发生改变,也能最大程度上保证反序列化成功率。不过如果类名改变,那么反序列化过程中会crash。
用法
public void put() {
Bundle bundle = new Bundle();
Tea tea = new Tea();
tea.setName("普洱");
tea.setPrice("13");
tea.setDescribe("清新可口,润喉滋养");
bundle.putSerializable("TEA", tea);
}
public void get() {
Tea tea = (Tea) bundle.getSerializable("TEA");
}
Parcelable
简介
Parcelable是Android专门提供类,实现的功能和Serialization一样,就是把对象转换为可存储和可传输的形式。不过原理同Serialization不同,Parcelable是把一个完整的对象分进行分解,每一部分都是Intent和Bundle支持的类型。
实现方式
package com.bs.trade.main.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* author : user_zf
* date : 18/3/17
* desc : 茶
*/
public class Tea implements Parcelable {
private String name;
private String price;
private String describe;
public Tea(){}
private Tea(Parcel source) {
name = source.readString();
price = source.readString();
describe = source.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(price);
dest.writeString(describe);
}
public static final Creator CREATOR = new Creator() {
@Override
public Tea createFromParcel(Parcel source) {
return new Tea(source);
}
@Override
public Tea[] newArray(int size) {
return new Tea[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
要注意的是,字段读取的顺序和写入的顺序必须保持一致。
用法
public void put() {
Bundle bundle = new Bundle();
Tea tea = new Tea();
tea.setName("普洱");
tea.setPrice("13");
tea.setDescribe("清新可口,润喉滋养");
bundle.putParcelable("TEA", tea);
}
public void get() {
Tea tea = bundle.getParcelable("TEA");
}
对比Serialization和Parcelable
- 在内存中使用的时候,Parcelable比Serialization性能高,推荐使用Parcelable,例如Activity、Fragment数据传递的场景
- Serialization会产生大量的临时变量,从而引起频繁的GC。
- Parcelable不能使用在将数据存储在磁盘的情况(如SD卡,网络传输),因为Parcelable不能很好的保证数据的持续性,此时推荐使用Serialization。
写于2018.03.17下午18:00(位置:深圳南山区)