简单点来说:Parcel就是一个存放读取数据的容器,
Android系统中的binder进程间通信(IPC)就使用了Parcel类来进行客户端与服务端数据的交互,而且AIDL的数据也是通过Parcel来交互的。在Java空间和C++都实现了Parcel,由于它在C/C++中,直接使用了内存来读取数据,因此,它更有效率。

分析Binder机制中的客户端与服务器端进行实际操作ontransact()函数 :

  1. //参数说明:
  2. // code :是请求的ID号
  3. // data :客户端请求发送的参数
  4. // reply:服务器端返回的结果
  5. // flags:一些额外的标识,如FLAG_ONEWAY等,通常为0.
  6. virtual status_t    onTransact( uint32_t code,
  7. );

从中我们可以看到Parcel的重要性以及窥探它的使用情况,接下来,我主要分析它的存储机制。

常用方法介绍:

obtain()                          获得一个新的parcel ,相当于new一个对象

dataSize()                      得到当前parcel对象的实际存储空间

dataCapacity()               得到当前parcel对象的已分配的存储空间, >=dataSize()值  (以空间换时间)

dataPostion()                 获得当前parcel对象的偏移量(类似于文件流指针的偏移量)

setDataPosition()          
设置偏移量

recyle()                           清空、回收parcel对象的内存

writeInt(int)                     写入一个整数

writeFloat(float)              写入一个浮点数

writeDouble(double)       写入一个双精度数

writeString(string)           写入一个字符串

当然,还有更多的writeXXX()方法,与之对应的就是readXXX(),具体方法请参阅SDK。

其中几个值得注意的方法为:

writeException()        在Parcel队头写入一个异常

writeException()        Parcel队头写入“无异常“

readException()        在Parcel队头读取,若读取值为异常,则抛出该异常;否则,程序正常运行。

一、Parcel的分析

相信看了前面的值,对Parcel的使用该有了初步印象。那么,Parcel的内部存储机制是怎么样的?偏移量又是

什么情况?让我们回忆一下基本数据类型的取值范围:

boolean     1bit          1字节

char          16bit         2字节

int             32bit        4字节

long          64bit        8字节

float          32bit        4字节

double       64bit         8字节

如果大家对C语言熟悉的话,C语言中结构体的内存对齐和Parcel采用的内存存放机制一样,即读取最小字节

为32bit,也即4个字节。高于4个字节的,以实际数据类型进行存放,但得为4byte的倍数。基本公式如下:

实际存放字节:

判别一:  32bit      (<=32bit)             例如:boolean,char,int

判别二:  实际占用字节(>32bit)     例如:long,float,String,数组等

当我们使用readXXX()方法时,读取方法也如上述:

实际读取字节:

判别一:  32bit      (<=32bit)            例如:boolean,char,int

判别二:  实际字节大小(>32bit)     例如:long,float,String,数值等

由上可以知道,当我们写入/读取一个数据时,偏移量至少为4byte(32bit),于是,偏移量的公式如下:

f(x)= 4x  (x=0,1,…n)

事实上,我们可以显示的通过setDataPostion(int postion) 来直接操作我们欲读取数据时的偏移量。毫无疑问,

你可以设置任何偏移量,但所读取的值是类型可能有误。因此显示设置偏移量读取值的时候,需要小心。

另外一个注意点就是我们在writeXXX()和readXXX()时,导致的偏移量是共用的,例如,我们在writeInt(23)后,

此时的datapostion=4,如果我们想读取5,简单的通过readInt()是不行的,只能得到0。这时我们只能通过

setDataPosition(0)设置为起始偏移量,从起始位置读取四个字节,即23。因此,在读取某个值时,可能需要使用

setDataPostion(int postion)使偏移量装换到我们的值处。

巧用setDataPosition()方法,当我们的parcel对象中只存在某一类型时,我们就可以通过这个方法来快速的读取

所有值。具体方法如下:

  1. /**
  2. * 前提条件,Parcel存在多个类型相同的对象,本例子以10个float对象说明:
  3. */
  4. public void readSameType() {
  5. Parcel ; i ; i++) {
  6. parcel.writeDouble(i);
  7. Log.i(TAG, "write double ----;
  8. int datasize = parcel.dataSize();
  9. while (i < datasize) {
  10. parcel.setDataPosition(i);
  11. double fvalue = parcel.readDouble();
  12. Log.i(TAG, " read double is=" + fvalue + ", --->" + getParcelInfo());
  13. i += 8; // double占用字节为 8byte
  14. }
  15. //      方法二,由于对象的类型一致,我们可以直接利用readXXX()读取值会产生偏移量
  16. //      parcel.setDataPosition(0)  ;  //
  17. //      while(parcel.dataPosition()<parcel.dataSize()){
  18. //          double fvalue = parcel.readDouble();
  19. //          Log.i(TAG, " read double is=" + fvalue + ", --->" + getParcelInfo());
  20. //      }
  21. }

由于可能存在读取值的偏差,一个默认的取值规范为:

1、  读取复杂对象时: 对象匹配时,返回当前偏移位置的该对象;

对象不匹配时,返回null对象 ;

2、  读取简单对象时: 对象匹配时,返回当前偏移位置的该对象 ;

对象不匹配时,返回0;

Android中Parcel的分析以及使用的更多相关文章

  1. Android中AppWidget的分析与应用:AppWidgetProvider .

    from: http://blog.csdn.net/thl789/article/details/7887968 本文从开发AppWidgetProvider角度出发,看一个AppWidgetPrv ...

  2. Android 中图片压缩分析(上)

    作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...

  3. android中SELINUX规则分析和语法简介【转】

    本文转载自:https://blog.csdn.net/LoongEmbedded/article/details/62430039 1. SELINUX是可以理解为一种Android上面的安全机制, ...

  4. android中SELINUX规则分析和语法简介

    1. SELINUX是可以理解为一种android上面的安全机制,是有美国国家安全局和一些公司设计的一个针对linux的安全加强系统我们可以通过配置SELINUX的相关policy,来定制自己的手机的 ...

  5. Android中Touch事件分析--解决HorizontalScrollView滑动和按钮事件触发问题

    之前写过关于HorizontalScrollView滑动和按钮事件触发问题,但是不能所有的情况,最近几天一直在想这个问题,今天有一个比较好的解决思路,最终应用在项目里面效果也很好,首先说明一下功能: ...

  6. Android中应用安装分析

    #1 安装方式 1 安装系统APK和预制APK时,通过PMS的构造函数中安装,即第一次开机时安装应用,没有安装界面. 2 网络下载安装,通过应用商店等,即调用PackageManager.instal ...

  7. Android中Context样式分析

    目录 1.样式定义以及使用 1.1.默认样式 1.2.样式定义及使用 1.3.当前样式下attr属性的获取 1.4.属性集合的定义与获取 2.Activity中Theme的初始化流程 2.1.系统调用 ...

  8. Android中Adapter和Bridge模式理解和应用

    一 Adapter模式 意图: 将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以在一起工作. 适用性: 使用一个已存在的类,而它的接口 ...

  9. Android中Input型输入设备驱动原理分析(一)

    转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反 ...

随机推荐

  1. Pytorch版本yolov3源码阅读

    目录 Pytorch版本yolov3源码阅读 1. 阅读test.py 1.1 参数解读 1.2 data文件解析 1.3 cfg文件解析 1.4 根据cfg文件创建模块 1.5 YOLOLayer ...

  2. 【Cuda编程】加法归约

    目录 cuda编程并行归约 AtomicAdd调用出错 gpu cpu下时间计算 加法的归约 矩阵乘法 矩阵转置 统计数目 平方和求和 分块处理 线程相邻 多block计算 cuda编程并行归约 At ...

  3. HDU 6128 Inverse of sum(同余)

    http://acm.hdu.edu.cn/showproblem.php?pid=6128 题意:有一个a数列,并且每个数都小于p,现在要求有多少对$(i,j)$满足$\frac{1}{a_i+a_ ...

  4. UVa 437 巴比伦塔

    https://vjudge.net/problem/UVA-437 这道题和HDU的Monkey and Banana完全一样. #include<iostream> #include& ...

  5. spring cloud kubernetes之serviceaccount permisson报错

    spring boot项目引用spring-cloud-starter-kubernetes <dependency> <groupId>org.springframework ...

  6. 【Python】【内置函数】【bytes&bytearray&str&array】

    [bytes] 英文文档: class bytes([source[, encoding[, errors]]]) Return a new “bytes” object, which is an i ...

  7. hdu 5672 String 尺取法

    String Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem D ...

  8. async 和 await的前世今生 (转载)

    async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...

  9. 遇到Io阻塞时会切换任务之【爬虫版】

    #! /usr/bin/env python3 # -*- coding:utf- -*- from urllib import request import gevent,time from gev ...

  10. docker运行python3.6+flask小记

    docker新手. 目的:开发运行多个web api项目的时候,方便开发,兼顾部署. 方案大概这样: 1 隔离:系统运行在容器里,1容器只起1进程,代替在host起多个venv或虚拟机: 2调试和备份 ...