目录
1、序列化与反序列化概念
2、序列化用途
3、Serializable实现序列化
4、 Parcelable实现序列化
5、Serializable与Parcelable区别
参考资料:Android开发艺术探索
一、概念
Java序列化是指把Java对象转换为字节序列的过程;
而Java反序列化是指把字节序列恢复为Java对象的过程。
二、用途
1、实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)
2、通过序列化对象在网络中传递对象。
3、通过序列化对象在进程间传递对象。
三、Serializable实现序列化
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的
对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可
Android Studio自动生成SerizlVersionUID:
1、File -> Settings... -> Editor -> Inspections -> Serialization issues -> Serializable class without ‘serialVersionUID‘(选中)
2、进入实现了Serializable中的类,选中类名,Alt+Enter弹出提示,然后直接导入完成.
package org.raphets.democollection;
import java.io.Serializable;
public class Dog implements Serializable{
private static final long serialVersionUID = -2457171891775313955L;
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
利用Serializable保存对象到本地
package org.raphets.democollection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
storageSerializableData();
getSerializableData();
}
/**
* 存储Serializable数据到本地
*/
private void storageSerializableData() {
List mDogs = new ArrayList<>();
Dog dog1 = new Dog("a", 3);
Dog dog2 = new Dog("b", 4);
Dog dog3 = new Dog("c", 2);
mDogs.add(dog1);
mDogs.add(dog2);
mDogs.add(dog3);
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
File file = new File(Environment.getExternalStorageDirectory().toString()
+ "/" + "dogs.dat");
if (!file.exists()) {
file.createNewFile();
}
fos = new FileOutputStream(file.toString());
oos = new ObjectOutputStream(fos);
oos.writeObject(mDogs);
} catch (Exception e) {
Log.i("TAG",e.toString());
} finally {
try {
if (oos != null)
oos.close();
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 读取本地的Seriablizable数据
*/
private void getSerializableData() {
FileInputStream fis=null;
ObjectInputStream ois=null;
File file = new File(Environment.getExternalStorageDirectory().toString()
+ "/" + "dogs.dat");
if (file.exists()){
try {
fis=new FileInputStream(file.toString());
ois=new ObjectInputStream(fis);
List mDogs= (List) ois.readObject();
for (Dog dog:mDogs){
Log.i("Dog",dog.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
四、 Parcelable实现序列化
Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
实现Parcelable接口主要可以分为一下几步:
1)implements Parcelable。
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从Parcel容器获取数据。
3)重写describeContents方法,内容接口描述,默认返回0即可。
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator 。
注意:若将Parcel看成是一个流,则先通过writeToParcel把对象写到流里面,再通过createFromParcel从流里读取对象,因此类实现的写入顺序和读出顺序必须一致。
package org.raphets.democollection;
import android.os.Parcel;
import android.os.Parcelable;
public class Dog implements Parcelable{
private String name;
private int age;
protected Dog(Parcel in) {
name = in.readString();
age = in.readInt();
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static final Creator CREATOR = new Creator() {
@Override
public Dog createFromParcel(Parcel in) {
return new Dog(in);
}
@Override
public Dog[] newArray(int size) {
return new Dog[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeInt(age);
}
}
五、Parcelable和Serializable的区别:
1、在使用内存的时候Parcelable比Serializable的性能高。
2、Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC(内存回收)。
3、Parcelable不能使用在将对象存储在磁盘上这种情况,因为在外界的变化下Parcelable不能很好的保证数据的持续性。
4、在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上
5、Parcelable是以Ibinder作为信息载体的.在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable
如何选择
Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化