Android序列化简析

目录
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进行数据持久化

你可能感兴趣的:(Android序列化简析)