今日推荐

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

引言

本篇文章目的在于详细的理解Parcelable的使用,而不是死记代码

我的简书博客地址 (由于csdn的图片经常出现不显示问题,以后就在简书写博客了)

特别鸣谢: Android中Parcel的解读

目录

  1. Parcelable的简单介绍
    1.1 Parcelable的简介
    1.2 Parcel的简介
    1.3 Parcelable中的三大过程介绍(序列化,反序列化,描述)
  2. Parcelable的使用和源码解读
  3. Parcelable中对象和集合的处理
  4. Parcelable和Serializable的区别和比较

1.1 Parcelable的简单介绍

介绍Parcelable不得不先提一下Serializable接口,Serializable是Java为我们提供的一个标准化的序列化接口,那什么是序列化呢? —- 简单来说就是将对象转换为可以传输的二进制流(二进制序列)的过程,这样我们就可以通过序列化,转化为可以在网络传输或者保存到本地的流(序列),从而进行传输数据 ,那反序列化就是从二进制流(序列)转化为对象的过程.

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

1.2 Parcel的简介

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

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

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

Parcelable通过Parcel实现了read和write的方法,从而实现序列化和反序列化,我们在源码中看一下

可以看出包含了各种各样的read和write方法,最终都是通过native方法实现

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

到这里,基本上关系都理清了,也明白简单的介绍和原理了,接下来在实现Parcelable之前,介绍下实现Parcelable的三大流程
首先写一个类实现Parcelable接口,会让我们实现两个方法

1.3.1 描述

其中describeContents就是负责文件描述,首先看一下源码的解读

通过上面的描述可以看出,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以

1.3.2 序列化

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

举个例子:我们将上面的User对象实现序列化,User对象包含三个字段 age,name,isMale

 /*** 该方法负责序列化* @param dest* @param flags*/
@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeInt(age);dest.writeString(name);// boolean 可以使用int或byte方式进行存储,怎么存就怎么取dest.writeInt(isMale ? 1 : 0);
}

1.3.3 反序列化

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

/*** 负责反序列化*/
public static final Creator<User> CREATOR = new Creator<User>() {/*** 从序列化后的对象中创建原始对象*/@Overridepublic User createFromParcel(Parcel source) {return new User(source);}/*** 创建指定长度的原始对象数组*/@Overridepublic User[] newArray(int size) {return new User[size];}
};public User(Parcel parcel) {age = parcel.readInt();name = parcel.readString();isMale = parcel.readInt() == 1;
}

2. Parcelable的实现和使用

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

这里实现Parcelable也很简单

1.写一个类实现Parcelable然后alt+enter 添加Parcelable所需的代码块,AndroidStudio会自动帮我们实现(这里需要注意如果其中包含对象或集合需要把对象也实现Parcelable)

3. Parcelable中对象和集合的处理

如果实现Parcelable接口的对象中包含对象或者集合,那么其中的对象也要实现Parcelable接口
如果包含对象Author和集合:

public class Book implements Parcelable {public int id;public String name;public boolean isCell;public ArrayList<String> tags;public Author author;// ***** 注意: 这里如果是集合 ,一定要初始化 *****public ArrayList<Author> authors = new ArrayList<>();public Book() {}
}

这里包含一个Author对象和Author集合

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

针对上面Book对象的序列化和反序列化的实现:

反序列化:

//反序列化
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];}
};protected Book(Parcel in) {id = in.readInt();name = in.readString();isCell = in.readByte() != 0;tags = in.createStringArrayList();// 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息author = in.readParcelable(Author.class.getClassLoader());//读取集合也分为两类,对应写入的两类//这一类需要用相应的类加载器去获取//in.readList(authors, Author.class.getClassLoader()); // 对应writeList//这一类需要使用类的CREATOR去获取in.readTypedList(authors, Author.CREATOR); //对应writeTypeList//authors = in.createTypedArrayList(Author.CREATOR);//对应writeTypeList//这里获取类加载器主要有几种方式getClass().getClassLoader();Thread.currentThread().getContextClassLoader();Author.class.getClassLoader();
}

序列化:

@Override
public void writeToParcel(Parcel dest, int flags) {//下面三种是基本类型就不多说dest.writeInt(id);dest.writeString(name);dest.writeByte((byte) (isCell ? 1 : 0));//序列化一个String的集合dest.writeStringList(tags);// 序列化对象的时候传入要序列化的对象和一个flag,// 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源dest.writeParcelable(author, flags);// 序列化一个对象的集合有两种方式,以下两种方式都可以//这些方法们把类的信息和数据都写入Parcel,以使将来能使用合适的类装载器重新构造类的实例.所以效率不高dest.writeList(authors);//这些方法不会写入类的信息,取而代之的是:读取时必须能知道数据属于哪个类并传入正确的Parcelable.Creator来创建对象// 而不是直接构造新对象。(更加高效的读写单个Parcelable对象的方法是:// 直接调用Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())dest.writeTypedList(authors);
}

写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些

一定要注意如果有集合定义的时候一定要初始化 like this –>
public ArrayList authors = new ArrayList<>();

4. Parcelable和Serializable的区别和比较

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

希望这篇文章可以帮助到需要的人,如果还有其他问题或者补充可以联系我~~~

详细介绍Android中Parcelable的原理和使用方法相关推荐

  1. Android中Parcelable的原理和使用方法

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

  2. 深度盘点:详细介绍机器学习中的7种交叉验证方法!

    来源:机器学习社区 本文约3400字,建议阅读10分钟 本文与你分享7种最常用的交叉验证技术及其优缺点,提供了每种技术的代码片段. 在任何有监督机器学习项目的模型构建阶段,我们训练模型的目的是从标记的 ...

  3. 【机器学习】深度盘点:详细介绍 Python 中的 7 种交叉验证方法!

    在任何有监督机器学习项目的模型构建阶段,我们训练模型的目的是从标记的示例中学习所有权重和偏差的最佳值. 如果我们使用相同的标记示例来测试我们的模型,那么这将是一个方法论错误,因为一个只会重复刚刚看到的 ...

  4. 介绍Android中的Paint和Canvas的概念和使用方法

    下面开始正式介绍内容 一.介绍Android中的Paint和Canvas的概念和使用方法 Android中的Paint和Canvas的概念是很简单的,就是我们用画笔在画布上进行绘制没什么难度的,我们只 ...

  5. 详细介绍android rom移植知识普及

    详细介绍android rom移植知识普及 最近接到很多兄弟们的求助,也回答过无数个和下面这个问题类似的问题: 如何编译android 原生代码得到一个rom,然后跑到某某手机上. 鉴于很多兄弟对这块 ...

  6. android studio parcelable,Android中Parcelable的使用详解

    Parcelable与Serializable Serializable是Java为我们提供的一个标准化的序列化接口. Parcelable是Android为我们提供的序列化的接口. 对比: 1.Pa ...

  7. Android中Parcelable接口用法

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

  8. [转]详细介绍java中的数据结构

    详细介绍java中的数据结构 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类.一起来看本文吧! 也许你已经熟练使用了java.util包里面的各 ...

  9. Android中Parcelable与Serializable接口用法

    转自: Android中Parcelable接口用法 1. Parcelable接口 Interface for classes whose instances can be written to a ...

最新文章

  1. 中科院、百度研究院等联合提出UGAN,生成图片难以溯源
  2. Freemarker和Spring开发:获取相对路劲和绝对路径的最优方式
  3. ipython/jupyter notebook修改文件存储路径和浏览器
  4. React Native 环境搭建步骤
  5. 微信公众号点击菜单即可打开并登录微站的实现方法
  6. windows 3.x编程指南_18000 MHz 可编程衰减器
  7. 线上分享 | 价值与风险,像投资者一样做产品决策
  8. 软件项目管理0824:标书中疫情条款
  9. python怎么画出圆润的曲线_利用python画出AUC曲线的实例
  10. mysql 日志记录 archive_完美起航-Mysql日志管理、备份与恢复
  11. 新年UI的拆红包源码/5级代理功能/会员中心充值接口完善
  12. MySQL 8.0中的JSON增强
  13. xshell 常用配置_Xshell连接报Connection closed by foreign host错误的解决办法
  14. 朱晔和你聊Spring系列S1E9:聊聊Spring的那些注解
  15. MongoDB从入门到高级的实战操作
  16. matlab 四分位距,四分位数及matlab实现
  17. 分层测试(Layered Testing Approach)
  18. QMap 迭代器崩溃分析
  19. Notepad++行首行尾批量添加字符
  20. 为什么SEO效果不明显

热门文章

  1. 写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度
  2. 一个应届生在深圳不平凡的一年
  3. Mysql 增删改查 Python交互01
  4. Python mac运行pygame一片空白不显示内容-解决方案
  5. Terminated due to memory error
  6. 北大操作系统陈向群第六章知识点
  7. 商业研究(18):以小见大,看互联网经济(4个股权众筹平台,10个项目)
  8. Oracle创建存储过程语法
  9. 【java并发编程】无锁并发框架disruptor
  10. 区块链技术:能源行业的恶魔还是天使?