尚拙

一个分享技术、学习成长的个人博客网站

0%

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<Dog> 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<Dog> mDogs= (List<Dog>) 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<Dog> CREATOR = new Creator<Dog>() {
@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可能不同,所以在序列化到存储设备或者网络传输方面还是尽量选择Serializable接口。