Android 数据序列化总结

简介: Android数据序列化总结 目录介绍 1.序列化简单介绍 1.1 序列化的概念 1.2 序列化是做什么用的 1.3 序列化的目的 2.Serializable的使用 2.1 什么是Serializable 2.

Android数据序列化总结

目录介绍

  • 1.序列化简单介绍

    • 1.1 序列化的概念
    • 1.2 序列化是做什么用的
    • 1.3 序列化的目的
  • 2.Serializable的使用

    • 2.1 什么是Serializable
    • 2.2 Serializable简单实现
  • 3.Parcelable的使用

    • 3.1 什么是Parcelable
    • 3.2 Parcelable简单实现
  • 4.Parcelable与Serializable的性能比较

    • 4.1 Serializable性能分析
    • 4.2 Parcelable性能分析
    • 4.3 性能比较总结描述
    • 4.4 性能测试方法分析
    • 4.5 两种如何选择
  • 5.数据的序列化方案

    • 5.1 数据序列化基础
    • 5.2 SQLite
    • 5.3 SharedPreferences
    • 5.4 JSON
  • 6.其他使用

    • 6.1 Intent传递数据
  • 7.其他介绍

    • 7.1 参考链接
    • 7.2 更新日志
    • 7.3 我的博客

0.备注

1.序列化的概念

  • 1.1 序列化的概念

    • 序列化是将Java对象转化成字节序列的过程
    • 反序列化是将字节序列恢复为Java对象的过程
    • 看到网上还有种说法:序列化的意思笼统的来说就是将对象转化成二进制,用于在文件或者网络上进行传输;反序列化就是相反,将序列化后的二进制转换成可以看懂的对象。
  • 1.2 序列化是做什么用的

    • 无论是在进程间通信、本地数据存储又或者是网络数据传输都离不开序列化的支持。而针对不同场景选择合适的序列化方案对于应用的性能有着极大的影响。
    • 从广义上讲,数据序列化就是将数据结构或者是对象转换成我们可以存储或者传输的数据格式的一个过程,在序列化的过程中,数据结构或者对象将其状态信息写入到临时或者持久性的存储区中,而在对应的反序列化过程中,则可以说是生成的数据被还原成数据结构或对象的过程。
    • 这样来说,数据序列化相当于是将我们原先的对象序列化概念做出了扩展,在对象序列化和反序列化中,我们熟知的有两种方法,其一是Java语言中提供的Serializable接口,其二是Android提供的Parcelable接口。而在这里,因为我们对这个概念做出了扩展,因此也需要考虑几种专门针对数据结构进行序列化的方法,如现在那些个开放API一般返回的数据都是JSON格式的,又或者是我们Android原生的SQLite数据库来实现数据的本地存储,从广义上来说,这些都可以算做是数据的序列化。
  • 1.3 序列化的目的

    • (1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中
    • (2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式)
    • (3).将对象数据在进程之间进行传递(Activity之间传递对象数据时,需要在当前的Activity中对对象数据进行序列化操作.在另一个Activity中需要进行反序列化操作讲数据取出)
    • (4).Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长(即每个对象都在JVM中)但在现实应用中,就可能要停止JVM运行,但有要保存某些指定的对象,并在将来重新读取被保存的对象。这是Java对象序列化就能够实现该功能。(可选择入数据库、或文件的形式保存)
    • (5).序列化对象的时候只是针对变量进行序列化,不针对方法进行序列化.
    • (6).在Intent之间,基本的数据类型直接进行相关传递即可,但是一旦数据类型比较复杂的时候,就需要进行序列化操作了.

2.Serializable的使用

  • 2.1 什么是Serializable

    • 正如前面提到的,Serializable接口是Java语言的特性,是最简单也是使用最广泛的序列化方案之一,这边需要注意的一点是Serializable接口是一个标识接口,无需实现方法,Java便会对这个对象进行序列化操作。
    • 在这里实现了Serializable接口的对象才可以序列化,将Java对象转换成字节序列,而对应的反序列化则是将字节序列恢复成Java对象的过程。
    • 在需要序列化的类中会用到serialVersionUID去标识这个序列化对象,即仅当序列化后的数据中的SerialVersionUID与当前类的serialVersionUID相同时才能被正常的反序列化。
  • 2.2 Serializable简单实现

    • 需要注意的:静态成员变量是属于类而不属于对象的,所以显然它不会参与到对象的序列化过程中。其次用transient关键字标记的成员变量不参与到序列化过程中。最后,这种序列化方式是基于磁盘或者网络的。
public class Person implements Serializable{
    private static final long serialVersionUID = -7060210544600464481L;
    private String name;
    private int 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;
    }
}

3.Parcelable的使用

  • 3.1 什么是Parcelable

    • Parcelable是Android SDK提供的,它是基于内存的,由于内存读写速度高于硬盘,因此Android中的跨进程对象的传递一般使用Parcelable。
  • 3.2 Parcelable简单实现

    • Android Parcelable code generator可以使用这个插件

      • 可以看出,实现一个Parcelable接口,需要实现以下几个方法:
      • 1.构造函数:从序列化后的对象中创建原始对象
      • 2.describeContents :接口内容的描述,一般默认返回0即可
      • 3.writeToParcel:序列化的方法,将类的数据写到parcel容器中
      • 4.静态的parcelable.Creator接口,这个接口包含两个方法

        • 1)createFormParcel:反序列化的方法,将Parcel还原成Java对象
        • 2)newArray:提供给外部类反序列化这个数组使用。
public class Book implements Parcelable{
    private String bookName;
    private String author;
    private int publishDate;

    public Book(){

    }

    //写一个构造方法或者set方法来方便写入数据
    public String getBookName(){
        return bookName;
    }

    public void setBookName(String bookName){
        this.bookName = bookName;
    }

    public String getAuthor(){
        return author;
    }

    public void setAuthor(String author){
        this.author = author;
    }

    public int getPublishDate(){
        return publishDate;
    }

    public void setPublishDate(int publishDate){
        this.publishDate = publishDate;
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags){
        //该方法将类的数据写入外部提供的Parcel中.即打包需要传递的数据到Parcel容器保存,
        //以便从parcel容器获取数据
        out.writeString(bookName);
        out.writeString(author);
        out.writeInt(publishDate);
    }

    public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>(){

     @Override
        public Book[] newArray(int size){
            //从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。
            return new Book[size];
        }

        @Override
        public Book createFromParcel(Parcel in){
            //从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。
            return new Book(in);
        }
    };

    public Book(Parcel in){
        //如果元素数据是list类型的时候需要: lits = new ArrayList<?> in.readList(list);
        //否则会出现空指针异常.并且读出和写入的数据类型必须相同.如果不想对部分关键字进行序列化,可以使用transient关键字来修饰以及static修饰.
        bookName = in.readString();
        author = in.readString();
        publishDate = in.readInt();
    }
}

4.Parcelable与Serializable的性能比较

  • 4.1 Serializable性能分析

    • Serializable是Java中的序列化接口,其使用起来简单但开销较大(因为Serializable在序列化过程中使用了反射机制,故而会产生大量的临时变量,从而导致频繁的GC),并且在读写数据过程中,它是通过IO流的形式将数据写入到硬盘或者传输到网络上。
  • 4.2 Parcelable性能分析

    • Parcelable则是以IBinder作为信息载体,在内存上开销比较小,因此在内存之间进行数据传递时,推荐使用Parcelable,而Parcelable对数据进行持久化或者网络传输时操作复杂,一般这个时候推荐使用Serializable。
  • 4.3 性能比较总结描述

    • 首先Parcelable的性能要强于Serializable的原因我需要简单的阐述一下
    • 1). 在内存的使用中,前者在性能方面要强于后者
    • 2). 后者在序列化操作的时候会产生大量的临时变量,(原因是使用了反射机制)从而导致GC的频繁调用,因此在性能上会稍微逊色
    • 3). Parcelable是以Ibinder作为信息载体的.在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable,既然是内存方面比价有优势,那么自然就要优先选择.
    • 4). 在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上.
    • 但是:虽然Parcelable的性能要强于Serializable,但是仍然有特殊的情况需要使用Serializable,而不去使用Parcelable,因为Parcelable无法将数据进行持久化,因此在将数据保存在磁盘的时候,仍然需要使用后者,因为前者无法很好的将数据进行持久化.(原因是在不同的Android版本当中,Parcelable可能会不同,因此数据的持久化方面仍然是使用Serializable)
  • 4.4 性能测试方法分析

    • 1)、通过将一个对象放到一个bundle里面然后调用Bundle#writeToParcel(Parcel, int)方法来模拟传递对象给一个activity的过程,然后再把这个对象取出来。
    • 2)、在一个循环里面运行1000 次。
    • 3)、两种方法分别运行10次来减少内存整理,cpu被其他应用占用等情况的干扰。
    • 4)、参与测试的对象就是上面的相关代码
    • 5)、在多种Android软硬件环境上进行测试
  • 4.5 两种如何选择

    • a)在使用内存方面,Parcelable比Serializable性能高,所以推荐使用Parcelable。
    • b)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
    • c)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性,在外界有变化的情况下,建议使用Serializable。

5.数据的序列化方案

  • 5.1 数据序列化基础

    • 下面讲到的是广义上的序列化方案,不同于前面两种狭义或者说是对象序列化方案,接下来的几种方案针对于数据的传输和存储过程中的序列化方案。
  • 5.2 SQLite

    • SQLite主要用于存储复杂的关系型数据,Android支持原生支持SQLite数据库相关操作(SQLiteOpenHelper),不过由于原生API接口并不友好,所以产生了不少封装了SQLite的ORM框架。
  • 5.3 SharedPreferences

    • SharedPreferences是Android平台上提供的一个轻量级存储API,一般用于存储常用的配置信息,其本质是一个键值对存储,支持常用的数据类型如boolean、float、int、long以及String的存储和读取。
  • 5.4 JSON

    • JSON是一种轻量级的数据交互格式,由于其相对于XML,体积更小,在网络上传输时更加介绍浏览,被广泛用于移动端。大部分APP与服务端的通信都是使用JSON格式进行交互。

6.其他使用

  • 6.1 Intent传递数据

    • 6.1.1 Serializable 方式

      • 相对简单,类及其内部的成员都实现Serializable接口即可,不需要额外的代码,但性能和速度上较慢。
      • 查看intent.putExtra()源码可知
public Intent putExtra(String name, Serializable value) {
    if (mExtras == null) {
        mExtras = new Bundle();
    }
    mExtras.putSerializable(name, value);
    return this;
}
    • 传递数据和接收数据代码
传递数据
Book book=new Book();
...
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("book",book);
startActivity(intent);

接收数据
Book book= (Book) getIntent().getSerializableExtra("book");
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());

7.其他介绍

  • 7.1 参考链接
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2256.html
https://www.jianshu.com/p/82e3090e00e0
http://www.developerphil.com/parcelable-vs-serializable/
  • 7.2 更新日志

    • v1.0.0 2017年3月28日
    • v1.1.0 2018年1月29日

*

目录
相关文章
|
1月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
39 1
|
2月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
|
9天前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
10 0
|
1月前
|
JSON 缓存 NoSQL
redis序列化数据时,如何包含clsss类型信息?
通过配置 `com.fasterxml.jackson.databind.ObjectMapper` 的 `enableDefaultTyping` 方法,可以使序列化后的 JSON 包含类信息。
45 2
|
2月前
|
存储 C# 数据库
解决C#对Firebase数据序列化失败的难题
在游戏开发中,Unity结合Firebase实时数据库为开发者提供强大支持,但在C#中进行数据序列化和反序列化时常遇难题。文章剖析了数据丢失或反序列化失败的原因,并给出解决方案,包括使用`JsonUtility`、确保字段标记为`[Serializable]`以及正确配置网络请求。示例代码演示了如何在Unity环境中实现Firebase数据的序列化和反序列化,并通过设置代理IP、Cookies和User-Agent来增强网络请求的安全性。这些技巧有助于确保数据完整传输,提升开发效率。
解决C#对Firebase数据序列化失败的难题
|
2月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
66 1
|
2月前
|
存储 分布式计算 Java
|
2月前
|
缓存 API Android开发
Android经典实战之Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate
本文介绍了Kotlin中`Flow`的`debounce`、`buffer`及`conflate`三个操作符。`debounce`过滤快速连续数据,仅保留指定时间内的最后一个;`buffer`引入缓存减轻背压;`conflate`仅保留最新数据。通过示例展示了如何在搜索输入和数据流处理中应用这些操作符以提高程序效率和用户体验。
47 6
|
2月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
2月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。