IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Serializable和Parcelable序列化 -> 正文阅读

[移动开发]Serializable和Parcelable序列化

前言

Android中常用的序列化方式包含有两种: Serializable和Parcelable。其中Serializable是java中通用的对象序列化方法,在Android实际内存操作时会更加偏向于实现Parcelable接口。

一、序列化和反序列化

序列化

由于存在内存中的对象都是暂时的,无法长期贮存,为了把对象的状态保持下来,这是需要把对象写入到磁盘中或者其他介质中,这个过程就叫做序列化。

反序列化

是序列化的反向操作。

概括性来说序列化是指将对象实例的状态存储到存储媒体(磁盘或者其他介质)的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

二、序列化应用场景

主要有以下情况(但不限于以下情况)
1)内存中的对象写入到硬盘;
2)数据传输(如Intent,Binder)

三、序列化流程

一个对象要实现序列化操作,该类就必须实现Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象类,而Parcelable接口则是android中特有的序列化接口,在某些情况下,Parcelable接口实现的序列化更为高效。

1. Serializable

在类声明中实现Serializable接口即可,建议可以主动声明序列化标识ID。标识ID是可以自动生成的,主动声明只是为了更高的保证反序列化正常。

序列化标识ID使用标识序列化类的,只有序列化标识一致,才能够正常的被反序列化。序列化和反序列化的ID必须相同才能欧股使序列化操作成功。

  1. 如果不去手动指定serialVersionUID的值,则编译器会根据当前的类结构计算出hash值作为UID
  2. 如果没有手动指定serialVersionUID的值,反序列化是当前的类有所改变,则计算出来的hash值就会不一致,就会使得当前的反序列化报错crash。
  3. 如果类结构发生了非常规性改变,例如修改了类名,修改了成员变量类型,这个时候即使UID验证通过了,反序列化也会报错,无法还原出一个新类型的结构对象。

示例代码

// 构造对象
        User user = new User();
        user.setId(1000);
        user.setName("张三");

        // 把对象序列化到文件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/serializable/user.txt"));
        oos.writeObject(user);
        oos.close();

        // 反序列化到内存
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/serializable/user.txt"));
        User userBack = (User) ois.readObject();
        System.out.println("read serializable user:id=" + userBack.getId() + ", name=" + userBack.getName());
        ois.close();

只需要采用ObjectOutStream和ObjectInputStream即可实现对象的序列化和反序列化操作。

反序列化后的对象是新创建的,和原对象不是同一个。

2. Parcelable

Parcelable是Android专用的序列化,内存上略优于Serializable,开销较小。

public class User implements Parcelable {

    public int id;
    public String name;
    public User friend;

    /**
     * 当前对象的内容描述,一般返回0即可
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 将当前对象写入序列化结构中
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.name);
        dest.writeParcelable(this.friend, 0);
    }

    public NewClient() {}

    /**
     * 从序列化后的对象中创建原始对象
     */
    protected NewClient(Parcel in) {
        this.id = in.readInt();
        this.name = in.readString();
       //friend是另一个序列化对象,此方法序列需要传递当前线程的上下文类加载器,否则会报无法找到类的错误
       this.friend=in.readParcelable(Thread.currentThread().getContextClassLoader());
    }

    /**
     * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
     * 重写接口中的两个方法:
     * createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
     * newArray(int size) 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用。
     */
    public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
        /**
         * 从序列化后的对象中创建原始对象
         */
        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }

        /**
         * 创建指定长度的原始对象数组
         */
        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
}

其实通过Intent传递复杂类型(如自定义引用类型数据)的数据时就需要使用Parcelable对象,如下是日常应用中Intent关于Parcelable对象的一些操作方法,引用类型必须实现Parcelable接口才能通过Intent传递,而基本数据类型,String类型则可直接通过Intent传递而且Intent本身也实现了Parcelable接口,所以可以轻松地在组件间进行传输。

四、两者的区别

1.实现差异

Serializable只需要实现Serializable接口即可,Parcelable需要实现Parcelable,,还要添加静态成员变量CREATOR,这个变量需要实现Creator接口,并实现读写的抽象方法。

2.两者的设计初衷

Serializable主要为了序列化对象到本地文件、数据库、网络流等。

Parcelable主要是因为Android中数据传递主要是在内存环境中,因此Parcelable的出现为了满足数据在内存中低开销而且高效的传递问题。

3. 应用场景

Parcelable是直接在内存中读写,我们知道内存的读写速度肯定优于硬盘读写速度,所以Parcelable序列化方式性能上要优于Serializable方式很多。所以Android应用程序在内存间数据传输时推荐使用Parcelable,如activity间传输数据和AIDL数据传递。

Serializable使用IO读写存储在硬盘上。序列化过程使用了反射技术,并且期间产生临时对象,优点代码少,在将对象序列化到存储设置中或将对象序列化后通过网络传输时建议选择Serializable。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:32:50  更:2022-03-16 22:35:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 18:57:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码