一、引言

  数据的序列化在Android开发中占据着重要的地位,无论是在进程间通信、本地数据存储又或者是网络数据传输都离不开序列化的支持。而针对不同场景选择合适的序列化方案对于应用的性能有着极大的影响。

  从广义上讲,数据序列化就是将数据结构或者是对象转换成我们可以存储或者传输的数据格式的一个过程,在序列化的过程中,数据结构或者对象将其状态信息写入到临时或者持久性的存储区中,而在对应的反序列化过程中,则可以说是生成的数据被还原成数据结构或对象的过程。

  这样来说,数据序列化相当于是将我们原先的对象序列化概念做出了扩展,在对象序列化和反序列化中,我们熟知的有两种方法,其一是Java语言中提供的Serializable接口,其二是Android提供的Parcelable接口。而在这里,因为我们对这个概念做出了扩展,因此也需要考虑几种专门针对数据结构进行序列化的方法,如现在那些个开放API一般返回的数据都是JSON格式的,又或者是我们Android原生的SQLite数据库来实现数据的本地存储,从广义上来说,这些都可以算做是数据的序列化。

二、Serializable接口

正如前面提到的,Serializable接口是Java语言的特性,是最简单也是使用最广泛的序列化方案之一,这边需要注意的一点是Serializable接口是一个标识接口,无需实现方法,Java便会对这个对象进行序列化操作。

在这里实现了Serializable接口的对象才可以序列化,将Java对象转换成字节序列,而对应的反序列化则是将字节序列恢复成Java对象的过程。

在需要序列化的类中会用到serialVersionUID去标识这个序列化对象,即仅当序列化后的数据中的SerialVersionUID与当前类的serialVersionUID相同时才能被正常的反序列化。

import java.io.*;
public class User implements Serializable{
private static final long serialVersionUID= 123456;
public int userId;
public String userName;
public boolean isMale;
public User(int userId,String userName,boolean isMale){
this.userId=userId;
this.userName=userName;
this.isMale = isMale;
}
public boolean toSerial(User user) throws IOException{
ObjectOutputStream out=null;
boolean status=false;
try{
out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
status=true;
}catch(FileNotFoundException e){
System.out.println("NO FILE");
}finally{
if(out!=null)
out.close();
}
return status;
}
public User toObject(String filename) throws IOException{
ObjectInputStream in=null;
boolean status=false;
User user=null;
try{
in = new ObjectInputStream(new FileInputStream(filename));
user=(User) in.readObject();
}catch(ClassNotFoundException e){
System.out.println("No file");
}finally{
if(in!=null)
in.close();
}
return user;
}
public static void main(String[] args) throws IOException{
User user = new User(0,"jake",true);
System.out.println(user.toSerial(user));
System.out.println(user.toObject("cache.txt").getClass());
}
}

此外,需要注意的:静态成员变量是属于类而不属于对象的,所以显然它不会参与到对象的序列化过程中。其次用transient关键字标记的成员变量不参与到序列化过程中。最后,这种序列化方式是基于磁盘或者网络的。

三、Parcelable接口

Parcelable接口是Android API提供的接口,从某种程度上来说,它更适用于Android平台上。不同于Serializable,它是基于内存的,由于内存中读写速度高于磁盘,所以Parcelable接口被广泛用于跨进程对象的传递。

下面贴上一个简单的Parcelable接口的序列化过程:

import android.os.Parcel;
import android.os.Parcelable;
public class User implements Parcelable {
public int userId;
public String userName;
public boolean isMale;
public User(int userId,String userName,boolean isMale) {
this.userId=userId;
this.userName=userName;
this.isMale=isMale;
} public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
} @Override
public User[] newArray(int size) {
return new User[size];
}
}; public User(Parcel in) {
userId=in.readInt();
userName = in.readString();
isMale=in.readInt()==1;
} @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(userId);
out.writeString(userName);
out.writeInt(isMale?1:0);
}
}

从上面可以看出,实现一个Parcelable接口,需要实现以下几个方法:

1.构造函数:从序列化后的对象中创建原始对象

2.describeContents :接口内容的描述,一般默认返回0即可

3.writeToParcel:序列化的方法,将类的数据写到parcel容器中

4.静态的parcelable.Creator接口,这个接口包含两个方法

1)createFormParcel:反序列化的方法,将Parcel还原成Java对象

2)newArray:提供给外部类反序列化这个数组使用。

四、两种对象序列化方法的对比

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

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

另外Serializable在使用时比较简单,而Parcelable在使用时需要手动去实现接口中的方法,为了规避使用Parcelable接口时的麻烦,我们下面介绍一个插件,从而自动生成对应的代码。

五、Parcelable插件

为了避免写大量的模板代码,这边介绍一个在Android Strudio中的插件,Android Parcelable code generator。在Pulgins中下载并按照该插件,接下来当我们需要用到Parcelable接口时,该插件就能自动帮我们将类对象转换成实现Parcelable接口的形式。

具体示例如下,

/**
* Created by DB on 2017/6/24.
*/ public class BookItem {
public String mName;
public long mLastTime;
public String mTitle;
public String mPath;
}

然后类似与生成getter和setter代码那样,我们就可以直接自动生成Parcelable形式的代码,结果如下所示:

import android.os.Parcel;
import android.os.Parcelable; /**
* Created by DB on 2017/6/24.
*/ public class BookItem implements Parcelable {
public String mName;
public long mLastTime;
public String mTitle;
public String mPath; @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mName);
dest.writeLong(this.mLastTime);
dest.writeString(this.mTitle);
dest.writeString(this.mPath);
} public BookItem() {
} protected BookItem(Parcel in) {
this.mName = in.readString();
this.mLastTime = in.readLong();
this.mTitle = in.readString();
this.mPath = in.readString();
} public static final Parcelable.Creator<BookItem> CREATOR = new Parcelable.Creator<BookItem>() {
@Override
public BookItem createFromParcel(Parcel source) {
return new BookItem(source);
} @Override
public BookItem[] newArray(int size) {
return new BookItem[size];
}
};
}

有了这个插件,使用Parcelable接口显然方便了许多(可以偷好多懒)

六、数据的序列化方案

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

1.SQLite

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

2.SharedPreferences

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

使用SharedPreferences读取和存储操作如下:

读取:

1) 获取Sharedpreferences对象

SharedPreferences mPreferences = context.getCSharedPreferences(PREFERENCES_NAME,Context.MODE_PRIVATE);

2.通过SharedPReferences对象读取存储在SharedPreferences中的数据

mPreferences.getBoolean(key,defValue);

存储:

1)获取SharedPreferences.Editor对象

SharedPreferences.Editor editor = mPreferences.edit();

2)通过SharedPreferences.Editor对象写入数据到SharedPreferences中。

mEditor.putBoolean(key,b);

3)调用commit函数将写入的数据提交,从而完成数据存储操作。

mEditor.commit();

3.JSON

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

几种Android数据序列化方案的更多相关文章

  1. 一种Android数据请求框架

    大部分Android应用一般都涉及到跟server的交互,除非是某些单机应用.既然要跟server打交道,向server请求数据差点儿是必做的事情,或许每家的APP都有一套自己的详细实现逻辑.但我们还 ...

  2. C基础 数据序列化简单使用和讨论

     前言 C中对序列化讨论少, 因为很多传输的内容都有自己解析的轮子. 对于序列化本质是统一编码, 统一解码的方式. 本文探讨是一种简单的序列化方案. 保证不同使用端都能解析出正确结果. 在文章一开始, ...

  3. 数据序列化导读(1)[JSON]

    所谓数据序列化(Data Serialization), 就是将某个对象的状态信息转换为可以存储或传输的形式的过程. 那么,为什么要进行序列化? 首先,为了方便数据存储: 其次,为了方便数据传递. 在 ...

  4. Android Learning:数据存储方案归纳与总结

    前言 最近在学习<第一行android代码>和<疯狂android讲义>,我的感触是Android应用的本质其实就是数据的处理,包括数据的接收,存储,处理以及显示,我想针对这几 ...

  5. 最经常使用的两种C++序列化方案的使用心得(protobuf和boost serialization)

    导读 1. 什么是序列化? 2. 为什么要序列化?优点在哪里? 3. C++对象序列化的四种方法 4. 最经常使用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序猿在编写应用程序的时候往往须 ...

  6. 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)

    导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序员在编写应用程序的时候往往需要将 ...

  7. iOS中几种数据持久化方案

    概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案: plist文件(属性列表) ...

  8. Android数据传递的五种方法汇总

    Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示,在例 ...

  9. PHP四种序列化方案

    原文地址:https://t.ti-node.com/thread/... 数据的序列化是一个非常有用的功能,然而目测很多人跟我一样,在刚接触这玩意的时候压根就不理解这货色到底是干啥用的,反正老师说了 ...

随机推荐

  1. haproxy安装配置for mysql负载均衡(ubantu)

    1.安装pcre apt-get update (apt-get install openssl libssl-dev  ==>可能需要安装的依赖包) apt-get install libpc ...

  2. 单词计数,杭电0j-2072

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=2072 [Problem Description] lily的好朋友xiaoou333最近很空,他想了一 ...

  3. Jenkins 发布后自动创建git tag

    为了便于项目中对发布的版本进行回滚,所以我们每次发布完成以后自动创建git tag. 1,创建一个Jenkins任务,命名成为push_tag_demo: 2,配置<源码管理>,这里配置比 ...

  4. 基于TypeScript的FineUIMvc组件式开发(开头篇)

    了解FineUIMvc的都知道,FineUIMvc中采用了大量的IFrame框架,对于IFrame的优缺点网上也有很多的讨论,这里我要说它的一个优点“有助于隔离代码逻辑”,这也是FineUIMvc官网 ...

  5. javaWeb学习总结(10)- EL函数库(2)

    一.EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...

  6. R + ggplot2 Graph Catalog(转)

    Joanna Zhao’s and Jenny Bryan’s R graph catalog is meant to be a complement to the physical book,Cre ...

  7. iOS安全攻防之使用 Charles 进行网络数据抓包 和 Paros 网络抓包

    Charles 是 Mac 系统下常用的网路抓包工具(Paros 也不错),windows 下常用 fiddler.正版的 Charles 是收费的(PS:支持正版),天朝人民比较喜欢破解版的Char ...

  8. Java静态代理与动态代理模式的实现

    前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...

  9. Eclipse用法:自动生成get和set方法

      方法一 Java的类中,除了常量声明为静态且公有的,一般的对象数据作用域,都是声明为私有的.这样做能保护对象的属性不会被随意改变,调试的时候也会方便很多:在类的公有方法中大一个调用栈就能看到哪里改 ...

  10. Ubuntu安装genymotion模拟器步骤

    1.安装VitrualBox genymotion模拟器需要有VirtualBox环境,打开终端(ctrl + alt + T),执行以下命令: sudo apt-get install virtua ...