Connor学Android - Serializable与Parcelable

在这里插入图片描述

Learn && Live

虚度年华浮萍于世,勤学善思至死不渝

前言

Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/Mndcr,话不多说我们马上开始!

1.Serializable接口

(1)实现Serializable接口

(2)声明serialVersionUID,实际上不声明也可以完成序列化,但可能无法完成反序列化,这一点稍后讨论

(3)保证类中的所有属性都是可序列化的(主要针对对象属性)

ByteArrayOutputStream bos = null;
ByteArrayInputStream bis = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;

try {
	// 序列化
	bos = new ByteArrayOutputStream();
	oos = new ObjectOutputStream(bos);
	oos.writeObject(this);
    
    // 反序列化
	bis = new ByteArrayInputStream(bos.toByteArray());
	ois = new ObjectOutputStream(bis);
	this = (Man) ois.readObject();
    } catch(Exception e) {}

几点说明:

(1)序列化、反序列化的过程可以实现对象的深克隆

(2)静态变量属于类不属于对象,不会参加序列化过程;用transient关键字标记的成员变量也不参与序列化过程

(3)序列化时系统会把当前类的serialVersionUID写入序列化的文件中或其他中介中,当反序列化的时候系统会去检测文件中的serialVersionUID是否与当前类的一致,一致则可以完成反序列化,否则说明当前类和序列化的类相比有变化(成员变量的数量、类型),系统重新计算当前类的hashCode并赋给serialVersionUID,导致比较不一致,无法正常反序列化,程序出现crash

2.Parcelable接口

Parcelable实现

实现Parcelable接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递

public class User implements Parcelable {
    public int userId;
    public String userName;
    public boolean isMale;
    public Book book;
    
    public User(int userId, String userName, boolean isMale) {
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
    }
    
    // 1
    public int describeContents() {
		return 0;
    }
    
    // 2
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(userId);
        out.writeString(userName);
        out.writeInt(isMale ? 1 : 0);
        out.writeParcelable(book, 0);
    }
    
    // 3
    public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
		public User createFromParcel(Parcel in) {
            return new User(in);
        }
        public User[] newArray(int size) {
            return new User[size];
        }
    };
    
    private User(Parcel in) {
        userId = in.readInt();
        userName = in.readString();
        isMale = in.readInt == 1;
        book = in.readParcelable(Thread.currentThread().getContextClassLoader());
    }
}

Parcel内部包装了可序列化的数据,可以在Binder中自由传输。由上述代码,Parcelable序列化过程需要实现的功能有注释1、2、3处的三个方法

(1)describeContents:内容描述,几乎在所有情况下都返回0,仅当当前对象中存在文件描述符时,返回1

(2)writeToParcel:序列化,最终是通过Parcel中的write方法完成

(3)CREATOR:反序列化,声明了如何创建序列化对象和数组,通过Parcel的read方法实现

需注意:

(1)Book类的对象book也必须为实现了Parcelable接口的可序列化对象,其反序列化过程需要传递当前线程的上下文类加载器,否则报ClassNotFound

(2)系统已经提供了许多实现了Parcelable接口的类,如Intent、Bundle、Bitmap等,同时List、Map也可以序列化,前提是其内元素皆可序列化

Parcelable方法

在这里插入图片描述

3.Serializable与Parcelable

Serializable是java中的序列化接口,并且使用起来简单,但是开销很大,序列化和反序列化过程需要大量的I/O操作,而Pracelable是android中的序列化,更适合在android平台上,缺点是使用起来麻烦,但是它的效率高,这是android推荐的序列化方式,通过Parcelable将对象序列化到存储设备中或者将对象序列化后通过网络传输也都是可以的,但是过程稍微复杂,因此在这两种情况下建议大家使用Serializable

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ConnorYan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值