Serializable vs Parcelable
Effective Android 系列
最近项目中在死磕性能,之前也大致总结了一个性能调优的大纲。光说不练假把式,既然 Java 有 Effective Java,那我也就写一篇 Effective Android 的系列文章,以记录我的死磕之路。
今天看到一位国外博主的一篇对比 Serializable 和 Parcelable 性能的文章,还附上了一个多设备对比的条形图。OMG,性能能有 10x 倍的提升?天下能有这等好事?不过本着求真的态度,还是写了一段测试代码来验证一下。这样一来,事情就变得有趣了。
先抛结论
有一定性能优势,但是完全没有那么悬殊。
测试设备: Google Pixel based on Oero。

1.全局图

2.放大图
Show Me the Code
SerializableComputer.java
public class SerializableComputer implements Serializable {
private String brand;
private String price;
private int year;
private double screenSize;
private String resolution;
private int usbPorts;
private int batterySize;
private ArrayList<String> serialNum;
public SerializableComputer(String brand, String price, int year, double screenSize, String resolution,
int usbPorts, int batterySize, ArrayList<String> serialNum) {
this.brand = brand;
this.price = price;
this.year = year;
this.screenSize = screenSize;
this.resolution = resolution;
this.usbPorts = usbPorts;
this.batterySize = batterySize;
this.serialNum = serialNum;
}
}
ParcelableComputer.java
public class ParcelableComputer implements Parcelable {
private String brand;
private String price;
private int year;
private double screenSize;
private String resolution;
private int usbPorts;
private int batterySize;
private ArrayList<String> serialNum;
public ParcelableComputer(String brand, String price, int year, double screenSize, String resolution,
int usbPorts, int batterySize, ArrayList<String> serialNum) {
this.brand = brand;
this.price = price;
this.year = year;
this.screenSize = screenSize;
this.resolution = resolution;
this.usbPorts = usbPorts;
this.batterySize = batterySize;
this.serialNum = serialNum;
}
protected ParcelableComputer(Parcel in) {
brand = in.readString();
price = in.readString();
year = in.readInt();
screenSize = in.readDouble();
resolution = in.readString();
usbPorts = in.readInt();
batterySize = in.readInt();
in.readStringList(serialNum);
}
public static final Creator<ParcelableComputer> CREATOR = new Creator<ParcelableComputer>() {
@Override
public ParcelableComputer createFromParcel(Parcel in) {
return new ParcelableComputer(in);
}
@Override
public ParcelableComputer[] newArray(int size) {
return new ParcelableComputer[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(brand);
dest.writeString(price);
dest.writeInt(year);
dest.writeDouble(screenSize);
dest.writeString(resolution);
dest.writeInt(usbPorts);
dest.writeInt(batterySize);
dest.writeStringList(serialNum);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Aaron";
private static final String BUNDLE_KEY = "BUNDLE_KEY";
private Button serializableBtn;
private Button parcelableBtn;
private SerializableComputer mSerializableComputer;
private ParcelableComputer mParcelableComputer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serializableBtn = (Button) findViewById(R.id.serializable_btn);
parcelableBtn = (Button) findViewById(R.id.parcelable_btn);
serializableBtn.setOnClickListener(mOnClickListener);
parcelableBtn.setOnClickListener(mOnClickListener);
initData();
}
private void initData() {
String brand = "Mac";
String price = "$2000";
int year = 2017;
double screenSize = 15.0;
String resolution = "2880 x 1800";
int usbPorts = 4;
int batterySize = 5000;
Random random = new Random(System.currentTimeMillis());
ArrayList<String> serialNums = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
serialNums.add(String.valueOf(random.nextInt()));
}
mSerializableComputer = new SerializableComputer(brand, price, year, screenSize, resolution, usbPorts, batterySize, serialNums);
mParcelableComputer = new ParcelableComputer(brand, price, year, screenSize, resolution, usbPorts, batterySize, serialNums);
}
View.OnClickListener mOnClickListener = v -> {
switch (v.getId()) {
case R.id.serializable_btn: {
for (int i = 0; i < 500; ++i) {
long start = System.nanoTime();
for (int j = 0; j < 10; ++j) {
Bundle bundle = new Bundle();
bundle.putSerializable(BUNDLE_KEY, mSerializableComputer);
SerializableComputer serializableComputer = (SerializableComputer) bundle.getSerializable(BUNDLE_KEY);
}
Log.d(TAG, "serializable: " + (System.nanoTime() - start));
}
break;
}
case R.id.parcelable_btn: {
for (int i = 0; i < 500; ++i) {
long start = System.nanoTime();
for (int j = 0; j < 10; ++j) {
Bundle bundle = new Bundle();
bundle.putParcelable(BUNDLE_KEY, mParcelableComputer);
ParcelableComputer parcelableComputer = bundle.getParcelable(BUNDLE_KEY);
}
Log.d(TAG, "parcelable: " + (System.nanoTime() - start));
}
break;
}
default: {
break;
}
}
};
}
All in All
虽然没有别人测出来 10x 倍的性能提升,或许和设备、Android 版本、甚至是写的代码有关系,不过至少我们也可以定性的得出一个结论,Parcelable 确实会比 Serializable 性能更好一些,不过这也是用更大的代码复杂度换来的。所以,代码只是一个工具,如果是为了快速开发和更低的维护成本,选择 Serializable 也未尝不可。如果死磕性能的话,Parcelable 又会是一个相对更好的选择。