经常阅读博客是个好习惯 
推荐技术小黑屋的Blog

Parcelable的简单介绍

介绍Parcelable不得不先提一下Serializable接口,Serializable是Java为我们提供的一个标准化的序列化接口,那什么是序列化呢?

进行Android开发的时候,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。简单来说就是将对象转换为可以传输的二进制流(二进制序列)的过程,这样我们就可以通过序列化,转化为可以在网络传输或者保存到本地的流(序列),从而进行传输数据 ,那反序列化就是从二进制流(序列)转化为对象的过程.

Parcelable是Android为我们提供的序列化的接口,Parcelable相对于Serializable的使用相对复杂一些,但Parcelable的效率相对Serializable也高很多,这一直是Google工程师引以为傲的,有时间的可以看一下Parcelable和Serializable的效率对比 Parcelable vs Serializable 号称快10倍的效率

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实现过程主要分为序列化,反序列化,描述三个过程,下面分别介绍下这三个过程。

Parcel的简介

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

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

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

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

什么是序列化

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

到这里,基本上关系都理清了,也明白简单的介绍和原理了,接下来在实现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);}
实现Parcelable的作用

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

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

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

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

  • describeContents 描述
    其中describeContents就是负责文件描述.通过源码的描述可以看出,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以

  • writeToParcel 序列化
    我们通过writeToParcel方法实现序列化,writeToParcel返回了Parcel,所以我们可以直接调用Parcel中的write方法,基本的write方法都有,对象和集合比较特殊下面单独讲,基本的数据类型除了boolean其他都有,Boolean可以使用int或byte存储

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

反序列化

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

Parcelable的使用和实现

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

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<>();

Parcelable和Serializable的区别和比较

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

选择序列化方法的原则

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

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

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

Parcelable相关推荐

  1. Serializable 都这么牛逼了,Parcelable 还要你何用?

    一些闲聊 距离上一篇文章似乎又是很久了,看起来也没有很多反馈,催更就更不用说了.哈哈,放弃了. 话说最近公司在招聘一批至少 5 年开发经验的 Android 开发工程师,我也是忙开了花,激动得不行呀. ...

  2. android开发之Parcelable使用详解

    想要在两个activity之间传递对象,那么这个对象必须序列化,android中序列化一个对象有两种方式,一种是实现Serializable接口,这个非常简单,只需要声明一下就可以了,不痛不痒.但是a ...

  3. java intent 传递集合对象_Intent之对象传递(Parcelable传递对象和对象集合)

    接着上一篇文章,以下我们讨论一下怎样利用Parcelable实现Intent之间对象的传递 一.实现对象传递 首先创建User.java实现Parcelable接口: package org.yayu ...

  4. Parcelable与Serializable的比较

    Parcel: Android中的序列化方式,可用于跨进程传输 Parcelable 进程间 如:想从一个第三方app拿进程回来 Serializable 进程内

  5. Android Parcelable的介绍与使用

    Parcelable使用的一个地方就是在进程间传递一个自定义的较为复杂的对象,对Parcelable学习了一下写下自己的观点. 将一个对象比如说一个名字为Cartoon的自定义类,由一个activit ...

  6. Android调用远程Service的参数和返回值都需要实现Parcelable接口

    import android.os.Parcel; import android.os.Parcelable; public class Person implements Parcelable{ p ...

  7. Android开发之Serializable 和 Parcelable的区别(源代码分享)

    android 中自定义的对象序列化的问题有两个选择一个是Parcelable,另外一个是Serializable. 一 序列化原因: 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.通过序 ...

  8. Android中Parcelable接口用法

    --  通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象.也可以将Parcel看成是一个流,通过writeToPa ...

  9. Android系统中Parcelable和Serializable的区别

    进行Android开发的时候,我们都知道不能将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递. 通过Android的A ...

  10. Serializable And Parcelable

    Intent在不同的组件中传递对象数据的应用非常普遍.下面介绍两种通过Intent传递对象的方法. 1.实现Serializable接口 2.实现Parcelable接口 为什么要将对象序列化? 1. ...

最新文章

  1. Java学习笔记3——继承
  2. js判断wifi_使用JS在浏览器中判断当前网络连接状态的几种方法
  3. Number 和 Math 类
  4. [旧文新读] 深度学习在Airbnb搜索的应用实践
  5. 简单入门Buffer
  6. python django ajax 逻辑推理_python django初识ajax
  7. PDFLib去水印办法
  8. 为Linux安装虚拟PDF打印机
  9. php识别二维码内容
  10. 基于FPGA的循迹小车,控制器:Xilinx-Ego1
  11. 2020 年你读了哪些觉得比较好的计算机书籍?
  12. Mac 终端连接和操作服务器常用命令
  13. python残差分析图
  14. 融合多头注意力机制的网络恶意流量检测
  15. 腾讯AI开放平台使用尝试:代理后的文本翻译API使用方式
  16. 禁止“无法验证发行者,确定要运行此软件吗”提示
  17. 支持向量机鸢尾花Iris数据集的SVM线性分类练习
  18. Thymeleaf【快速入门】
  19. 【Protle99SE】PCB中各层的含义【小汇】
  20. 洛谷P2738 [USACO4.1]篱笆回路Fence Loops(Floyed求最小环)

热门文章

  1. 用计算机寻找素数,找出1到1000所有质数(电脑流程图)
  2. 浅析小流域综合治理评价指标体系和评价方法
  3. Linux-USB驱动笔记(一)
  4. autodyn之状态方程(EOS)
  5. ListaryPro
  6. Nexus 7 二代 刷机
  7. 19数字媒体技术1班 刘增千PS笔记5
  8. 套料软件XSuperNEST产品及成功因素介绍
  9. 浏览器保存网页的四种方式
  10. 2021全国计算机技术与软件专业技术资格水平考试(软考)网络管理员考试大纲