几种Android数据序列化方案
一、引言
数据的序列化在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数据序列化方案的更多相关文章
- 一种Android数据请求框架
大部分Android应用一般都涉及到跟server的交互,除非是某些单机应用.既然要跟server打交道,向server请求数据差点儿是必做的事情,或许每家的APP都有一套自己的详细实现逻辑.但我们还 ...
- C基础 数据序列化简单使用和讨论
前言 C中对序列化讨论少, 因为很多传输的内容都有自己解析的轮子. 对于序列化本质是统一编码, 统一解码的方式. 本文探讨是一种简单的序列化方案. 保证不同使用端都能解析出正确结果. 在文章一开始, ...
- 数据序列化导读(1)[JSON]
所谓数据序列化(Data Serialization), 就是将某个对象的状态信息转换为可以存储或传输的形式的过程. 那么,为什么要进行序列化? 首先,为了方便数据存储: 其次,为了方便数据传递. 在 ...
- Android Learning:数据存储方案归纳与总结
前言 最近在学习<第一行android代码>和<疯狂android讲义>,我的感触是Android应用的本质其实就是数据的处理,包括数据的接收,存储,处理以及显示,我想针对这几 ...
- 最经常使用的两种C++序列化方案的使用心得(protobuf和boost serialization)
导读 1. 什么是序列化? 2. 为什么要序列化?优点在哪里? 3. C++对象序列化的四种方法 4. 最经常使用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序猿在编写应用程序的时候往往须 ...
- 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)
导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序员在编写应用程序的时候往往需要将 ...
- iOS中几种数据持久化方案
概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案: plist文件(属性列表) ...
- Android数据传递的五种方法汇总
Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示,在例 ...
- PHP四种序列化方案
原文地址:https://t.ti-node.com/thread/... 数据的序列化是一个非常有用的功能,然而目测很多人跟我一样,在刚接触这玩意的时候压根就不理解这货色到底是干啥用的,反正老师说了 ...
随机推荐
- mybatis mapper.xml 写关联查询 运用 resultmap 结果集中 用 association 关联其他表 并且 用 association 的 select 查询值 报错 java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mybatis.map
用mybaits 写一个关联查询 查询商品表关联商品规格表,并查询规格表中的数量.价格等,为了sql重用性,利用 association 节点 查询 结果并赋值报错 商品表的mapper文件为Gooo ...
- [刷题]算法竞赛入门经典(第2版) 4-5/UVa1590 - IP Networks
书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 代码:(Accepted,0 ms) //UVa1590 - IP Networks #include<iost ...
- React入门---基础知识-大纲-1
-----------------在慕课网学习react入门笔记-------------- ---------博主边学边记录,手把手进行学习及记录---------- --------------- ...
- SpringData系列一 Spring Data的环境搭建
本节作为主要讲解Spring Data的环境搭建 JPA Spring Data :致力于减少数据访问层(DAO)的开发量.开发者唯一要做的就是声明持久层的接口,其他都交给Spring Data JP ...
- Android 工程集成React Native 0.44 注意点
当前(2017年5月22日 )React Native开发相当火爆,但是搜索下来,没有最新版本0.44集成的教程,因此尝试了一下如何集成到Android原生工程中去.本篇旨在记录出现的问题以及应对方式 ...
- 初码-Azure系列-迁移PHP应用至Azure的一些实践记录和思考
最近客户在逐步迁移应用从阿里云到Azure,这次又轮到一个PHP+MySQL应用了,顺便也记一下流水账. 需求:迁移部署在阿里云上的ECS服务器(系列2,IO优化+2核4G+50G的SSD云盘+10M ...
- swift学习 - tableView自适应高度1(xib autoLayout)
tableView自适应高度 效果图: 源码: class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSo ...
- STM32串口控制步进电机(原创)
用的42步进电机: 厂家可能不一样,两项四线步进电机,里面有两个线圈.在电机什么电都没有接的情况下,用万用表测量四个管脚:两两短接(或者阻值很小)的为一组,可以分别接A+,a-剩余接B+,B-;顺序可 ...
- java中几种获取项目路径方式
转自http://caodaoxi.iteye.com/blog/1234805 在jsp和class文件中调用的相对路径不同. 在jsp里,根目录是WebRoot 在class文件中,根目录 ...
- JavaScript基础(.....持续待更)
javascript热身 一.你知道,为什么JavaScript非常值得我们学习吗? 1. 所有主流浏览器都支持JavaScript. 2. 目前,全世界大部分网页都使用JavaScript. 3. ...