今天和同学交流传递集合数据时候,我直接建议同学使用putSerializable传递一个序列化对象,然后获取到该对象中list集合拿来使用,但是同学说她们不这样用使用putParcelableArrayListExtra直接传递一个集合,我就有点好奇这两者有什么不同,我当初为什么使用第一种方法,就去网上查了资料,大彻大悟。


自定义对象的传递:

通过intent 传递自定义对象的方法有两个,第一是实现Serialization接口,第二是实现Parcelable接口。

首选推荐Parceable,android中的很多数据类型都是实现Serialable接口方式来传递的,例如 Intent、Bundle、Bitmap、Uri等等。


android Parcelable化的提供了一个接口 Parcelable和一个工具类 Parcel


Parcelable:一个规范接口,定义实现Parcelable需要实现的功能


Parcel:数据存取的工具类,供用户在实现Parcelable接口时存取自定义数据用,也供系统传递数据时使用。

Parcelable实现要点:需要实现三个东西
1)writeToParcel 方法。该方法将类的数据写入外部提供的Parcel中.声明如下:
writeToParcel (Parcel dest, int flags) 具体参数含义见javadoc
2)describeContents方法。没搞懂有什么用,反正直接返回0也可以
3)静态的Parcelable.Creator接口,本接口有两个方法:
createFromParcel(Parcel in) 实现从in中创建出类的实例的功能
newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。

看到上面解释后我明白了两者都可以传递自定义对象,那它们有什么不同之处呢?

一 序列化原因:

1.永久性保存对象,保存对象的字节序列到本地文件中;
2.通过序列化对象在网络中传递对象;
3.通过序列化在进程间传递对象。 

二 至于选取哪种可参考下面的原则:

1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。

看到上面解释后,我才知道自己犯了多大错误。

同样也抱着对Parcelable的好感和好奇心去做了一个Demo进行测试。在测试过程中也碰到了一些问题总结如下:

1、仅仅传递一个自定义对象,自定义对象中都是基本数据类型(集合类型也是基本数据类型),直接实现Parcelable接口,按照提示实现其中方法,通过putExtra传递即可。

2、传递的自定义对象中含有集合(此处的自定义对象实现了Parcelable接口),集合中的数据也是自定义对象类型(集合必须是ArrayList,否则会报错),此时需要注意以下两点:

Parcelable接口和Serialization接口),传递数据时候直接报错:Parcel: unable to marshal value

Serialization接口或者Parcelable接口,实现Parcelable接口时候,注意集合要用ArrayList定义,最开始我在protected构造方法中使用的是ClassLoader.getSystemClassLoader(),运行报错:android.os.BadParcelableException: ClassNotFoundException when unmarshal 修改为Books.class.getClassLoader()即可

Parcelable传递自定义对象真是呕心沥血

,现附上代码,以供参考。

3、直接传递集合,集合中的bean实现Parcelable接口,使用putParcelableArrayListExtra传递数据,注意:要使用ArrayList定义集合。

Students.java:

public class Students implements Parcelable {
    public ArrayList<Books> list;
    public Students(ArrayList<Books> list){
        this.list = list;

    }
    protected Students(Parcel in) {
        list = in.readArrayList(Books.class.getClassLoader());
    }

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

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

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeList(list);
    }

}

Books.java:

public class Books implements Parcelable{
    public String name;
    public int price;
    public  Books(String name,int price){
        this.name = name;
        this.price = price;
    }


    protected Books(Parcel in) {
        name = in.readString();
        price = in.readInt();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(price);
    }
}