Parcelable vs Serializable

自古美人都是妖i 提交于 2020-10-30 03:04:31

###Parcelable vs Serializable

在一开始学习Android的时候,我们就知道了不能在Activity和Fragment之间直接传递对象,必须使用Intent或者Bundle。 查看api后,我们发现有两个选择,让我们的对象要么实现Parcelable,要么实现Serializable。作为Java开发者,我们都知道Serializable机制,那么为什么还需要Parcelable呢? 要接解答这个问题,先来看两个列子

####Serializable-简洁之至

// access modifiers, accessors and constructors omitted for brevity
public class SerializableDeveloper implements Serializable
    String name;
    int yearsOfExperience;
    List<Skill> skillSet;
    float favoriteFloat;

    static class Skill implements Serializable {
        String name;
        boolean programmingRelated;
    }
}

正如你所见到的,只需要在类和成员变量引用类实现Serializable接口就可以了,并且不需要实现任何方法。其他的事情统统交给Java去做,简洁之至。 但是Serializable的问题就是处理太慢,Java是采用反射去实现序列号操作。并且在处理序列化的时候还会生成大量的对象,导致GC频繁发生。

####Parcelable-速度之王

// access modifiers, accessors and regular constructors ommited for brevity
class ParcelableDeveloper implements Parcelable {
String name;
int yearsOfExperience;
List<Skill> skillSet;
float favoriteFloat;

ParcelableDeveloper(Parcel in) {
    this.name = in.readString();
    this.yearsOfExperience = in.readInt();
    this.skillSet = new ArrayList<Skill>();
    in.readTypedList(skillSet, Skill.CREATOR);
    this.favoriteFloat = in.readFloat();
}

void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(yearsOfExperience);
    dest.writeTypedList(skillSet);
    dest.writeFloat(favoriteFloat);
}

int describeContents() {
    return 0;
}


static final Parcelable.Creator<ParcelableDeveloper> CREATOR
        = new Parcelable.Creator<ParcelableDeveloper>() {

    ParcelableDeveloper createFromParcel(Parcel in) {
        return new ParcelableDeveloper(in);
    }

    ParcelableDeveloper[] newArray(int size) {
        return new ParcelableDeveloper[size];
    }
};

static class Skill implements Parcelable {
    String name;
    boolean programmingRelated;

    Skill(Parcel in) {
        this.name = in.readString();
        this.programmingRelated = (in.readInt() == 1);
    }

    @Override
    void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(programmingRelated ? 1 : 0);
    }

    static final Parcelable.Creator<Skill> CREATOR
        = new Parcelable.Creator<Skill>() {

        Skill createFromParcel(Parcel in) {
            return new Skill(in);
        }

        Skill[] newArray(int size) {
            return new Skill[size];
        }
    };

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

根据google开发人员所说,这段代码执行速度会有明显的提升。其中一个原因是,我们正在明确有关序列化过程,而不是使用反射来推断它。这里也可以看到,代码为实现这个目的做了大量的优化。 然而Parcelable也不是免费的,它需要按规则编写大量的代码模板去实现序列化过程,并且难以阅读。

####性能测试

那么问题来了,Parcelable究竟有多快?

#####测试步骤

  1. 在Activity中使用Bundle#writeToParcel(Parcel, int)方法将一个对象写入,然后再取出来来模仿对象传递的过程。
  2. 重复运行1000次
  3. 取10次平均值,为了反映不同内存使用,其他app不同cpu消耗等情况
  4. 使用上面的SerializableDeveloperParcelableDeveloper进行测试
  5. 在不同手机不行版本下运行 + LG Nexus 4 - Android 4.2.2 + Samsung Nexus 10 - Android 4.2.2 + HTC Desire Z - Android 2.3.3

#####测试结果

测试结果

Nexus 10 Serializable: 1.0004ms, Parcelable: 0.0850ms - 10.16x 提升. Nexus 4 Serializable: 1.8539ms - Parcelable: 0.1824ms - 11.80x 提升. Desire Z Serializable: 5.1224ms - Parcelable: 0.2938ms - 17.36x 提升.

结果就是这样,Parcelable至少比Serializable快10倍。而且还可以看到,即使在Nexus 10上,一个相对简单对象做一次完整的serialize/deserialize也需要1毫秒。

####结论

如果你想做一个优秀的开发者,请尽量使用Parcelable。因为Parcelable至少会快10倍而且占用更少的内存。 在大多数情况下,缓慢的Serializable也不会被特别注意到。用它也不会有多大关系,但是请记住,它是一个昂贵的操作。 如果你试着传递数以千计的Serializable对象数组或列表,处理整个过程可能需要花费超过一秒的时间。就会导致页面跳转或者横竖屏切换呆滞。

####后记

如果你看到了这里,我就会给你免费赠送一个大礼包! 手动写Parcelable实在是太麻烦了,而且大部分都是复制黏贴改动。网上的工具类原理也是使用apt生成代码,然后反射执行,对效率还是稍稍有点影响。 幸运的是,现在AndroidStudio已经有了辅助插件——Android Parcelable Code Generator。使用这款插件可以方便的自动生成Parcelable代码。

安装方法:

  1. 下载安装包
  2. 打开IntelliJ或者Android Studio
  3. Settings -> Preferences -> Plugins -> Install plugin from disk....
  4. 选择下载的安装包

在win中按下alt+Insert,mac按下command+N。效果如下: 生成代码

参考资料 http://www.developerphil.com/parcelable-vs-serializable/ https://plugins.jetbrains.com/plugin/7332?pr=androidstudio https://github.com/mcharmas/android-parcelable-intellij-plugin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!