Android 中Serializable以及Parcelable两种序列化的使用以及区别

本文深入探讨了Android中序列化机制,对比Serializable与Parcelable接口的使用,解析其在数据传输及存储中的优劣,指导开发者如何根据场景选择最适合的序列化方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当我们在进行页面的跳转时,需要通过Intent或者Bundle来传输对象或者集合,这时候就需要序列化将对象转换为可以传输的二进制流。通过Intent或者是Bundle中的源码发现除了可以传输基本数据类型,还可以传输下面两种数据 Parcelable value 以及Serializable value
在这里插入图片描述
序列化:将一个对象转换成可存储或可传输的状态(二进制流)。序列化后的对象可以在网络上进行传输,也可以存储到本地。
反序列:将二进制流转换为对象的过程
序列化的主要作用

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

1 Serializable简介
Serializable是Java中的一个提供序列化的接口,可以为对象提供序列化和反序列化。Serializable接口是一个空接口,使用起来非常方便,只需要将准备序列化的类实现该接口即可。

public interface Serializable {
/* empty */
}

这样子就实现了序列化
public class BookBean implements Serializable{
    
}

2 Parcelable简介
Parcelable是Android sdk提供的用实现于数据序列化的一个接口,可以为对象提供序列化和反序列化。Paecelable实现的方式略复杂一些,需要重写
describeContents 以及writeToParcel 方法,并且创建一个静态的不可修改的CREATOR 匿名内部类

缺少set 和  get  序列化和反序列话的顺序保持一致 也就是BookBean(Parcel in)以及writeToParcel(Parcel parcel, int i) 顺序保持一致
public class BookBean implements Parcelable {
    //基本数据类型
    private int bookId;
    private String bookName;
    private String bookAuthor;
    private String bookPrice;
    //静态内部对象
    private BookSubject bookSubject;
    // list 中存放的基本数据类型
    private ArrayList<String> tagList;
    // list 中存放的是对象   
    // ***** 注意: 这里如果是集合 ,一定要初始化 *****
    private ArrayList<BookSubject> list = new ArrayList<>();

    public BookBean() {
    }

    // 将流转换为对象
    public BookBean(Parcel in) {
        //读取基本数据类型
        bookId = in.readInt();
        bookName = in.readString();
        bookAuthor = in.readString();
        bookPrice = in.readString();

 //     读取基本数据的list
        tagList = in.createStringArrayList();// 返回 ArrayList<String>
        
        //读取对象 两种方式 第一种读取对象需要提供一个类加载器去读取
        // 第二种 传入对象的CREATOR
        bookSubject = in.readParcelable(BookSubject.class.getClassLoader());
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//            bookSubject = in.readTypedObject(BookSubject.CREATOR);
//        }

        //读取存放引用对象的list 第一种需要使用类的CREATOR去获取 对应的 writeTypeList
        in.readTypedList(list, BookSubject.CREATOR);
        //第二种 需要用相应的类加载器去获取 对应writeList
//        in.readList(list,BookSubject.class.getClassLoader());

//        这里获取类加载器主要有几种方式
//        getClass().getClassLoader();
//        Thread.currentThread().getContextClassLoader();
//        BookBean.class.getClassLoader();

    }

    // 负责反序列化
    public static final Creator<BookBean> CREATOR = new Creator<BookBean>() {
        @Override
        public BookBean createFromParcel(Parcel in) {
            return new BookBean(in);
        }

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

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

    /**
     *  序列化
     */
    @Override
    public void writeToParcel(Parcel parcel, int i) {
        //序列化基本数据类型
        parcel.writeInt(bookId);
        parcel.writeString(bookName);
        parcel.writeString(bookAuthor);
        parcel.writeString(bookPrice);

        //序列化基本数据类型的list
        parcel.writeStringList(tagList);

        // 序列化引用对象 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源
        parcel.writeParcelable(bookSubject, 0);

//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//            parcel.writeTypedObject(bookSubject,0);
//        }

        // 序列化引用类型对象的list
        parcel.writeTypedList(list);
    }


    public static class BookSubject implements Parcelable {

        private String subject;

        public BookSubject() {
        }

        protected BookSubject(Parcel in) {
            subject = in.readString();
        }

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

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

        public String getSubject() {
            return subject;
        }

        public void setSubject(String subject) {
            this.subject = subject;
        }

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

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

测试代码快
 BookBean bookBean = new BookBean();
//基本数据类型
 bookBean.setBookId(1);
 bookBean.setBookAuthor("阿萨德");
 bookBean.setBookName("水浒传");
 bookBean.setBookPrice("¥24");
 //引用类型的对象
 BookBean.BookSubject bookSubject = new BookBean.BookSubject();
 bookSubject.setSubject("巴萨");
 bookBean.setBookSubject(bookSubject);
 //引用类型对象的数组
 ArrayList<BookBean.BookSubject> list = new ArrayList<>();
 list.add(bookSubject);
 bookBean.setList(list);
 //基本数据类型的数组
 ArrayList<String> tagsList = new ArrayList<>();
 tagsList.add("皇家马德里");
 bookBean.setTagList(tagsList);
 Intent intent = new Intent(MainActivity.this, MainActivity2.class);
 intent.putExtra("testData", bookBean);
 startActivity(intent);
 BookBean bookBean = getIntent().getParcelableExtra("testData");
//基本数据类型
 Log.i("TAG", "onCreate: " + bookBean.getBookAuthor());
 //基本数据类型的list
 Log.i("TAG", "onCreate: " + bookBean.getTagList().get(0));
 //引用类型对象
 Log.i("TAG", "onCreate: " + bookBean.getBookSubject().getSubject());
 //引用类型对象的list
 Log.i("TAG", "onCreate: " + bookBean.getList().get(0).getSubject());

写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些

Parcelable和Serializable的区别和比较
Parcelable和Serializable都是实现序列化并且都可以用于Intent间传递数据,
Serializable是Java的实现方式,对象持久化到磁盘,序列化和反序列化需要进行大量的IO操作, 序列化的过程要用到反射,会创建许多的临时变量,容易触发GC,所以消耗比较大,但是实现方式简单
Parcelable是Android提供的方式,效率比较高,但是实现起来复杂一些 , 比Serializable性能高,速度差不多是10倍左右吧

序列化是需要注意两点:

1 静态成员变量属于类不属于对象,所以不参与序列化
2 用transient关键字标记的成员变量不参与序列化

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

快速实现序列化:
在这里插入图片描述点击完成安装,重启as ,快捷键 Alt + Insert
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值