更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680
本篇文章将从以下几个内容来阐述数据传输与序列化:

  • [Serializable原理]
  • [Parcelable的原理和使用方法]
  • [json]

一、Serializable原理

  • 1.概念

    • 序列化:把Java对象转换为字节序列的过程。
    • 反序列化:把字节序列恢复为Java对象的过程。
  • 2.用途 对象的序列化主要有两种用途:

    • 1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。
    • 2)在网络上传送对象的字节序列。

  • 所谓的Serializable,就是java提供的通用数据保存和读取的接口。至于从什么地方读出来和保存到哪里去都被隐藏在函数参数的背后了。这样子,任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。这样子极大的简化了类的设计。只要设计一个保存一个读取功能就能解决上面说得所有问题。
  • java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。
  • 工作流当中流程变量的几种数据类型:string、integer、short、long、double、boolean、date、binary、serializable,这就是为什么要将javabean实现序列化的原因,因为你将对象设置到流程变量中必须要实现序列化,否则会在设置流程变量的时候报错找不到该类型。
  • java对象序列化机制就是把内存中的Java对象(User之类的JavaBean)转换成二进制流。java对象序列化后可以很方便的存储或者在网络中传输。
  • Java的序列化机制是通过运行时判断类的序列化ID(serialVersionUID)来判定版本的一致性。
  • 在反序列化时,java虚拟机会通过二进制流中的serialVersionUID与本地的对应的实体类进行比较,如果相同就认为是一致的,可以进行反序列化,正确获得信息,否则抛出序列化版本不一致的异常。
  • 所以涉及到数据传输或者存储的类,严格意义上来说都要加上序列化ID,这也是一种良好的编程习惯

二、Parcelable的原理和使用方法

2.1 Android源码中的Parcelable

/*** Interface for classes whose instances can be written to* and restored from a {@link Parcel}.  Classes implementing the Parcelable* interface must also have a non-null static field called <code>CREATOR</code>* of a type that implements the {@link Parcelable.Creator} interface.* * <p>A typical implementation of Parcelable is:</p>* * <pre>* public class MyParcelable implements Parcelable {*     private int mData;**       public int describeContents() {*         return 0;*     }**     public void writeToParcel(Parcel out, int flags) {*         out.writeInt(mData);*     }**     public static final Parcelable.Creator<MyParcelable> CREATOR*             = new Parcelable.Creator<MyParcelable>() {*         public MyParcelable createFromParcel(Parcel in) {*             return new MyParcelable(in);*         }**         public MyParcelable[] newArray(int size) {*             return new MyParcelable[size];*         }*     };*     *     private MyParcelable(Parcel in) {*         mData = in.readInt();*     }* }</pre>*/

通过源码中的介绍 可以知道,Parcelable接口的实现类是可以通过Parcel写入和恢复数据的,并且必须要有一个非空的静态变量 CREATOR,而且还给了一个例子,这样我们写起来就比较简单了,但是简单的使用并不是我们的最终目的,通过查看Android源码中Parcelable可以看出,Parcelable实现过程主要分为序列化,反序列化,描述三个过程,下面分别介绍下这三个过程。

2.2 Parcel的简介

在介绍之前我们需要先了解Parcel是什么?Parcel翻译过来是打包的意思,其实就是包装了我们需要传输的数据,然后在Binder中传输,也就是用于跨进程传输数据

简单来说,Parcel提供了一套机制,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象,下图是这个过程的模型。

Parcel可以包含原始数据类型(用各种对应的方法写入,比如writeInt(),writeFloat()等),可以包含Parcelable对象,它还包含了一个活动的IBinder对象的引用,这个引用导致另一端接收到一个指向这个IBinder的代理IBinder。
Parcelable通过Parcel实现了read和write的方法,从而实现序列化和反序列化

2.3 Parcelable中的三大过程介绍(序列化,反序列化,描述)

2.3.1 什么是序列化

序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

到这里,基本上关系都理清了,也明白简单的介绍和原理了,接下来在实现Parcelable之前,介绍下实现Parcelable的三大流程 .
[图片上传中...(image.png-73288d-1522235519935-0)]

我先把代码贴出来

public class Album implements Parcelable {/*** 负责反序列化*/private static final Creator<Album> CREATOR = new Creator<Album>() {/*** 从序列化对象中,获取原始的对象* @param source* @return*/@Overridepublic Album createFromParcel(Parcel source) {return new Album(source);}/*** 创建指定长度的原始对象数组* @param size* @return*/@Overridepublic Album[] newArray(int size) {return new Album[0];}};private final String mId;private final String mCoverPath;private final String mDisplayName;private final long mCount;Album(String id, String coverPath, String displayName, long count) {mId = id;mCoverPath = coverPath;mDisplayName = displayName;mCount = count;}Album(Parcel source) {mId = source.readString();mCoverPath = source.readString();mDisplayName = source.readString();mCount = source.readLong();}/*** 描述* 返回的是内容的描述信息* 只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以** @return*/@Overridepublic int describeContents() {return 0;}/*** 序列化** @param dest* @param flags*/@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(mId);dest.writeString(mCoverPath);dest.writeString(mDisplayName);dest.writeLong(mCount);}

2.3.2 实现Parcelable的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

首先写一个类实现Parcelable接口,会让我们实现两个方法:

  • describeContents 描述
    其中describeContents就是负责文件描述.通过源码的描述可以看出,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以
  • writeToParcel 序列化
    我们通过writeToParcel方法实现序列化,writeToParcel返回了Parcel,所以我们可以直接调用Parcel中的write方法,基本的write方法都有,对象和集合比较特殊下面单独讲,基本的数据类型除了boolean其他都有,Boolean可以使用int或byte存储

我们将上面的Album对象实现序列化,Album对象包含四个字段。

2.3.4 反序列化

反序列化需要定义一个CREATOR的变量,上面也说了具体的做法,这里可以直接复制Android给的例子中的,也可以自己定义一个(名字千万不能改),通过匿名内部类实现Parcelable中的Creator的接口

2.4 Parcelable的使用和实现

根据上面三个过程的介绍,Parcelable就写完了,就可以直接在Intent中传输了,可以自己写两个Activity传输一下数据试一下,其中一个putExtra另一个getParcelableExtra即可。

2.5 Parcelable中对象和集合的处理

import android.os.Parcel;
import android.os.Parcelable;import java.util.ArrayList;/*** Created by fengxing on 2018/3/28.*/public class ParcelDemo implements Parcelable {private int count;private String name;private ArrayList<String> tags;private Book book;// ***** 注意: 这里如果是集合 ,一定要初始化 *****private ArrayList<Book> books = new ArrayList<>();/*** 序列化** @param in*/protected ParcelDemo(Parcel in) {count = in.readInt();name = in.readString();tags = in.createStringArrayList();// 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息book = in.readParcelable(Book.class.getClassLoader());//读取集合也分为两类,对应写入的两类//这一类需要用相应的类加载器去获取in.readList(books, Book.class.getClassLoader());// 对应writeList//这一类需要使用类的CREATOR去获取in.readTypedList(books, Book.CREATOR); //对应writeTypeList//books = in.createTypedArrayList(Book.CREATOR); //对应writeTypeList//这里获取类加载器主要有几种方式getClass().getClassLoader();Thread.currentThread().getContextClassLoader();Book.class.getClassLoader();}public static final Creator<ParcelDemo> CREATOR = new Creator<ParcelDemo>() {@Overridepublic ParcelDemo createFromParcel(Parcel in) {return new ParcelDemo(in);}@Overridepublic ParcelDemo[] newArray(int size) {return new ParcelDemo[size];}};/*** 描述** @return*/@Overridepublic int describeContents() {return 0;}/*** 反序列化** @param dest* @param flags*/@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(count);dest.writeString(name);//序列化一个String的集合dest.writeStringList(tags);// 序列化对象的时候传入要序列化的对象和一个flag,// 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源dest.writeParcelable(book, 0);// 序列化一个对象的集合有两种方式,以下两种方式都可以//这些方法们把类的信息和数据都写入Parcel,以使将来能使用合适的类装载器重新构造类的实例.所以效率不高dest.writeList(books);//这些方法不会写入类的信息,取而代之的是:读取时必须能知道数据属于哪个类并传入正确的Parcelable.Creator来创建对象// 而不是直接构造新对象。(更加高效的读写单个Parcelable对象的方法是:// 直接调用Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())dest.writeTypedList(books);}
}

Book类,需要先实现Parcelable,实现步骤就不贴出来了,和普通的对象一样,实现三个过程

import android.os.Parcel;
import android.os.Parcelable;/*** Created by fengxing on 2018/3/28.*/public class Book implements Parcelable {protected Book(Parcel in) {}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {}
}

写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些
一定要注意如果有集合定义的时候一定要初始化 like this –>public ArrayList<T> demo = new ArrayList<>();

2.6 Parcelable和Serializable的区别和比较

Parcelable和Serializable都是实现序列化并且都可以用于Intent间传递数据,Serializable是Java的实现方式,可能会频繁的IO操作,所以消耗比较大,但是实现方式简单 Parcelable是Android提供的方式,效率比较高,但是实现起来复杂一些 , 二者的选取规则是:内存序列化上选择Parcelable, 存储到设备或者网络传输上选择Serializable(当然Parcelable也可以但是稍显复杂)

2.6.1 选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

三 json

3.1 json

一种数据传输格式,与开发语言无关,轻量级。
一开始是javaScript的,但是后面比较流传,几乎所有语言都有相应的使用API。

3.2 数据结构

Object---对象
  使用花括号{}包含的键值对结构
  Key必须是String类型,value为任何基本类型或者数据结构(对象,或者数组)

Array---数组
  使用中括号[]来起始,并用逗号,来分隔元素

基本类型:
   string number true false null
例如:

{"name" :"王小二","age": 22,"birthday" : "1990-12-1", 注意:json里没有Date这种时间的类型,所以用string;需要了解一下时间戳"school" : "蓝翔","major": ["理发","挖掘机"],"has_girlfriend":false,"car": null,"house": null,"commont": "这是一个注释"
}
注意:
json中没有注释的写法,但是我们可以曲线救国{"id":"1","author":{"id":"1506200043","name":"kylin","gender":1},"major":["理发","挖掘机"]
}

java对json有支持,在使用的时候需要引入以下包:

commons-beanutils.xxx.jar
    commons-collections.xxx.jar
    commons-lang.xxx.jar
    commons-logging.jar
    json-lib.xxx.jar
    ezmorph.xxx.jar

JSON字符串的常用生成方式:----------从后端发送给前端的数据
1.使用map来放key-value数据,然后转换成json对象--再转换成json字符串---再发送给前端

//map(javaObject)--->jsonObject---->jsonStr ----前端
import net.sf.json.JSONObject;
public void jsonStrByMap(){//构建map对象,并且把需要发送给前端的东西添加进入
Map<String,String> params=new HashMap<>();
params.put("status","200");
params.put("username","kylin");
params.put("password","123456");
params.put("sexy","male");
params.put("userID","15062");//java对象变成json对象
JSONObject jsonObject=JSONObject.fromObject(params);//json对象转换成json字符串
String jsonStr=jsonObject.toString();System.out.println(jsonStr);
}

2.使用javabean来构建json

User.java
public class User {private String username;private String password;public String getUsername() {
return username;
}public void setUsername(String username) {
this.username = username;
}public String getPassword() {
return password;
}public void setPassword(String password) {
this.password = password;
}}
//javabean---json对象---json字符串---->前端
public void jsonStrByJavaBean(){//创建一个User对象
User user=new User();
user.setUsername("kylin");
user.setPassword("123456");//java对象转换成json对象
JSONObject jsonObject=JSONObject.fromObject(user);//json对象转换成json字符串
String jsonStr=jsonObject.toString();
System.out.println(jsonStr);
}

从前端获取的数据------>转换成后端可以用的数据
json字符串转换成java对象

//前端传递过来的是json字符串,那么我们对这个字符串需要进行获取并且处理
//json字符串-----json对象------java对象
JSONObject jsonobject = JSONObject.fromObject(jsonStr);
User user=(User)JSONObject.toBean(jsonobject,User.class);
//然后就通过user对象来操作了
String username=user.getUsername();
String password=user.getPassword();

json字符串转换成map对象

JSONObject jsonobject = JSONObject.fromObject(jsonStr);
Map params=(Map) jsonObject;
//然后就可以通过map来操作了
//判断是否有username字段和username字段
if (params.containsKey("username")){System.out.println(params.get("username"));
}
if (params.containsKey("password")){System.out.println(params.get("password"));
}

更多Android架构进阶视频学习请点击:https://space.bilibili.com/474380680
参考:https://www.cnblogs.com/shan-kylin/p/9218680.html
https://www.cnblogs.com/chenmingjun/p/9746310.htmlhttps://www.jianshu.com/p/df35baa91541

android 序列化_Android高级架构进阶之数据传输与序列化相关推荐

  1. 在腾讯工作是怎么样的体验,Android高级架构进阶之数据传输与序列化

    前段时间腾讯上了一波微博热搜,相信大家都看到了: 那我们从加班开始说起吧,正好也是大家关心的点. 从网上流出的加班管理机制表上看,"双休"确实是双休,但"不加班" ...

  2. 未雨绸缪:Java高级架构进阶必学之 ⑥ 大知识要点附视频学习资料

    程序员,一个令人向往的职业,看起来有着高薪酬.高技术,还是一群高智商.头脑灵活的人.事实上,程序员的工作,让人非常抓狂,程序员的生活,异常线性单调.而且技术更新快,相互之间竞争压力非常大~~ 相信你可 ...

  3. GitHub标星8-3k的学习习惯,未来的Android高级架构师:别让这几个点毁了你

    4.记得带上最少两份简历,你可以针对公司做不同的简历,没有任何一份简历是万能的,自己准备一支笔.现在虽然天气热,但别穿个短裤就跑来-至少也要打扮的像个上班族. 5.面试的时候一直在问你关于java,而 ...

  4. 阿里Android高级架构师:一个牛逼的插件又双叒诞生了!

    作者:鸿洋 原文链接:https://mp.weixin.qq.com/s/GdDkzR8AvgHROUiGwYtfOg 前言 大家在写 Android 项目的时候,免不了要引入各种 Google 提 ...

  5. 如何成为一名Android架构师,乃至高级架构师,文末有路线图

    很多Android的小伙伴在做了多年的开发之后,始终搞不清楚达到Android架构师需要何种技能,我们对比着Android高级工程师来说明. 我们先来看一下Android高级工程师的招聘要求 职位描述 ...

  6. 技术进阶:Kubernetes高级架构与应用状态部署

    在了解Kubernetes应用状态部署前,我们先看看Kubernetes的高级架构,方便更好的理解Kubernetes的状态. Kubernetes 的高级架构 包括应用程序部署模型,服务发现和负载均 ...

  7. cs架构用什么语言开发_C、C++、Go 语言、Linux服务器开发高级架构师进阶之路

    C++这门语言从诞生到今天已经经历了将近30个年头.不可否认,它的学习难度都比其它语言较高.而它的学习难度,主要来自于它的复杂性. 现在C++的使用范围比以前已经少了很多,Java.C#.Python ...

  8. C/C++Linux服务器开发高级架构师/Linux后台开发架构师丨高级进阶学习

    01 课程介绍 [录播]课程介绍(66分钟) 免费试学 [录播]磁盘存储链式的B树与B+树(131分钟) 免费试学 免费学习视频链接点击:C/C++Linux服务器开发高级架构师/Linux后台架构师 ...

  9. Linux C/C++后台开发高级架构师进阶指南-剑指腾讯T9

    C++后台开发是一个庞杂的技术栈,因为没有统一的开发框架并且应用行业非常广泛.所有涉猎广泛,这里就把C/C++++后台开发的技术点进行整理总结,看完以后,不会让你失望的. -------------- ...

最新文章

  1. TKStudio-LPC1220_GPIO_LED工程后记
  2. python 替换空格
  3. 如何去写一手好 SQL?
  4. ALEIDoc EDI(6)--Filter Conversion
  5. 推荐一个有趣的Chrome扩展程序-查看任意网站的开发技术栈
  6. 关于form组件的补充-------formChoice
  7. jboss默认进程名称_快速指南:剖析JBoss BPM跨进程通信
  8. 软件工程中的启发规则
  9. 数据挖掘肿瘤预测_喜欢临床预测模型|SEER数据挖掘的期刊有哪些
  10. MQ(消息队列)常见的应用场景解析
  11. 自定义注解实现(spring aop)
  12. 4.TCP/IP 详解卷1 --- ARP:地址解析协议
  13. LINUX安装文件DEB的postrm运行报错,无法卸载怎么办
  14. 手机app通达信添加自定义公式(分时T+0)为例子讲解
  15. 知识图谱构建流程详解
  16. (3)资源管理-- Effective C++改善程序与设计的55个具体做法(Effective C++: 55 Specific Ways to Improve Your Programs)
  17. 用开源代码如何建立网站_建立全球开源法律网络
  18. 自动化网络安全防御的问题
  19. Linux apt-get 安装离线包
  20. ride导入自定义python库

热门文章

  1. 碾压ES和MongoDB,RedisJson横空出世!
  2. 15 种 SQL 优化中,老司机才懂的处理技巧
  3. 超专业解析!10分钟带你搞懂Linux中直接I/O原理
  4. Amazon 63岁员工因算法评分太低被自动开除!
  5. 终于有人把 java代理 讲清楚了,万字详解!
  6. 扒中台的“祖坟”!对不起,Supercell的“中台”,你学不会
  7. 解密京东618大促数据库运维的攻守之道
  8. 你说你懂互联网,那这些你知道么?
  9. Spring Cloud剖析--云平台技术栈17
  10. 基于深度学习的肺癌预测诊断