[架构基本功]Parcelable序列化

Android组件化架构

近来在使用Android序列化的时候遇到一些问题因此这里记录一下,一个不当心你面试就可能面上了。面试

何时使用序列化?bash

Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE自己就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也能够用于进程间通讯(IPC))。实现Serializable接口很是简单,声明一下就能够了,而实现Parcelable接口稍微复杂一些,但效率更高,在通常的时候推荐用这种方法提升性能。架构

###Parcelable和Serializable的区别ide

1)在使用内存的时候,Parcelable比Serializable性能高,因此推荐使用Parcelable,除了如下介绍的坑问题。组件化

2)Serializable在序列化的时候会产生大量的临时变量,从而引发频繁的GC。性能

3)Parcelable不能使用在要将数据存储在磁盘上的状况,由于Parcelable不能很好的保证数据的持续性在外界有变化的状况下。尽管Serializable效率低点,但此时仍是建议使用Serializable 。学习

1.可是会有特殊的时候,例如如下代码有什么问题?ui

public class Person implements Parcelable {
    public String name;
    public int age;
    public List<Person> childlist;

    protected Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
        childlist = in.createTypedArrayList(Person.CREATOR);
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeTypedList(childlist);
    }
}
复制代码

估计一眼看不出有什么问题,问题就在于若是List childlist若是包含了当前的Person对象,序列化的时候,就会致使循环引用,一直序列化直到栈溢出,因此这里须要很是当心。有些时候为了代码抽象方便,极可能就会所以忽视了一些问题。spa

2.ParcelIn和writeToParcel的读和写的顺序须要是一致的,否则序列化会出错。code

3.每次新加入属性,须要记得手动再次生成Parceble相应的方法。AS编译器生成是最稳的,别做死本身写。

4.抽象继承传递问题。 Person抽象类方法

public abstract class Person implements Parcelable {
    public String name;
    public int age;
    public List<Person> childlist;

    protected Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
        childlist = in.createTypedArrayList(Person.CREATOR);
        job = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeTypedList(childlist);
        dest.writeString(job);
    }

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

    abstract String getJob();

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in) {
                @Override
                String getJob() {
                    return "";
                }
            };
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}
复制代码

Father实类

public class Father extends Person{
    public String job;

    protected Father(Parcel in) {
        super(in);
    }

    @Override
    String getJob() {
        return "soft engineer";
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest,flags);
    }
}
复制代码

这样一开始看没什么问题,能够正常传递。可是使用intent传递的时候,通过序列化后颇有可能会数据丢失。由于抽象方法致使,某些数据序列化失败。

这种场景有两种解决方法

1.使用Serializable来序列化

2.将序列化操做移动到父类进行。

固然若是你有更好的写法能够联系我吧。

我创建了一个关于Android架构学习的群,里面能够进一步进行组件化学习和架构思想的的交流。

群号是316556016,也能够扫码进群。我在这里期待大家的加入!!!

Android组件化架构

组件化架构2群
相关文章
相关标签/搜索