(一)Serializable
Android应用是用java开发,那么java序列化Serializable也是可以使用的,java序列化优点是使用简洁,开销较大,适合用用于存取到设备上 如SD卡等。
把需要序列化数据类接入Serializable接口就可以了,如果有不想序列化的数据还可以用 transient 来取消这个变量的序列化。代码如下:
package com.xue.qin.demo.myserialization;
import java.io.Serializable;
/**
* Created by xue.qin on 2017/6/5.
*/
public class MyObject implements Serializable {
private int n;
private String name;
transient String useless;
public MyObject(int n, String name, String useless) {
this.n = n;
this.name = name;
this.useless = useless;
}
@Override
public String toString() {
return "( n:" + n + " name:" + name + " useless:" + useless + " 地址:" + super.toString()+" )";
}
}
MyObject obj1, obj2, obj3;
MyObject obj4, obj5, obj6;
try {
obj2 = new MyObject(1, "dog","here");
obj1 = obj2;
obj3 = new MyObject(2, "cat","there");
Log.i(TAG, "写入的对象\n");
Log.i(TAG, "obj1 = " + obj1 + " ");
Log.i(TAG, "obj2 = " + obj2 + " ");
Log.i(TAG, "obj3 = " + obj3 + " \n");
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buf);
out.writeObject(obj1);
out.writeObject(obj2);
out.writeObject(obj3);
ByteArrayInputStream bufin = new ByteArrayInputStream(buf.toByteArray());
ObjectInputStream in = new ObjectInputStream(bufin);
obj4 = (MyObject) in.readObject();
obj5 = (MyObject) in.readObject();
obj6 = (MyObject) in.readObject();
Log.i(TAG, "读取的对象\n");
Log.i(TAG, "obj4 = " + obj4 + " ");
Log.i(TAG, "obj5 = " + obj5 + " ");
Log.i(TAG, "obj6 = " + obj6 + " ");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
01-04 18:21:58.302 18984-18984/? I/ObjectNet: 写入的对象
01-04 18:21:58.302 18984-18984/? I/ObjectNet: obj1 = ( n:1 name:dog useless:here 地址:com.xue.qin.demo.myserialization.MyObject@e3956d8 )
01-04 18:21:58.302 18984-18984/? I/ObjectNet: obj2 = ( n:1 name:dog useless:here 地址:com.xue.qin.demo.myserialization.MyObject@e3956d8 )
01-04 18:21:58.303 18984-18984/? I/ObjectNet: obj3 = ( n:2 name:cat useless:there 地址:com.xue.qin.demo.myserialization.MyObject@9effa31 )
01-04 18:21:58.310 18984-18984/? I/ObjectNet: 读取的对象
01-04 18:21:58.310 18984-18984/? I/ObjectNet: obj4 = ( n:1 name:dog useless:null 地址:com.xue.qin.demo.myserialization.MyObject@b4abe69 )
01-04 18:21:58.311 18984-18984/? I/ObjectNet: obj5 = ( n:1 name:dog useless:null 地址:com.xue.qin.demo.myserialization.MyObject@b4abe69 )
01-04 18:21:58.311 18984-18984/? I/ObjectNet: obj6 = ( n:2 name:cat useless:null 地址:com.xue.qin.demo.myserialization.MyObject@30d40ee )
可以看到,写入时候地址完全一致,符合我们一贯的想法,没啥说的。读取回来的obj4和obj5地址也是一致的,也就是说obj4和obj5是指向同一个引用的。
可见序列化的时候是将引用的关系也写入了,并不是简单的根据引用复制一个对象,而是还复制了对象的指向关系。
另外作为transient 标记的变量useless没有被序列化。
(二)Parcelable
android为了进程间的通信能够高效率的传送信息,使用parcel,必须要接入这个接口parcelable。代码例子如下,使用中可以接入此接口。
package com.xue.qin.demo.myparcelableclass;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by xue.qin on 2017/6/5.
*/
public class MyObject implements Parcelable {
private int n;
private String name;
private String useless;
public MyObject(){
n=0;
name="default";
useless="default";
}
public MyObject(int n, String name, String useless) {
this.n = n;
this.name = name;
this.useless = useless;
}
public MyObject(Parcel source) {
readFromParcel(source);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(n);
dest.writeString(name);
dest.writeString(useless);
}
public void readFromParcel(Parcel source) {
this.n = source.readInt();
this.name = source.readString();
this.useless = source.readString();
}
public static final Parcelable.Creator CREATOR = new Creator() {
@Override
public MyObject createFromParcel(Parcel source) {
MyObject myObject2 = new MyObject(source);
return myObject2;
}
@Override
public MyObject[] newArray(int size) {
return new MyObject[size];
}
};
@Override
public String toString() {
return "( n:" + n + " name:" + name + " useless:" + useless + " 地址:" + super.toString() + " )";
}
}
关键点2、必须按照规范写 writeToParcel和readFromParcel(为什么Parcelable接口中没有这个方法??),(参数定向tag为 out , inout ,会调用))
关键点3、必须按照规范写 public static final Parcelable.Creator
接口提供了可供外部调用的静态对象,提供从parcel读取初始化类实例的渠道。,
问题:为什么非得声明为CREATE这个变量名?
是因为例如在AIDL自动生成的代码中就会使用者个变量来创建parcelable的类实例。(相信系统中还要有类似的调用与写法,例如系统中的MotionEvent类就是这样写的)
com.xue.qin.demo.myparcelableclass.MyObject.CREATOR.createFromParcel(data);
既然安卓提供了这样简洁的写法与规定,最好写成CREATOR。