麦子学院Android开发教程Parcel的分析及使用.docx_第1页
麦子学院Android开发教程Parcel的分析及使用.docx_第2页
麦子学院Android开发教程Parcel的分析及使用.docx_第3页
麦子学院Android开发教程Parcel的分析及使用.docx_第4页
麦子学院Android开发教程Parcel的分析及使用.docx_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

IT在线教育平台麦子学院:在android开发中,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. const Parcel& data,8. Parcel* reply,9. uint32_t flags = 0);复制代码从中我们可以看到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) 例如:long,float,String,数组等 当我们使用readXXX()方法时,读取方法也如上述: 实际读取字节: 判别一:32bit (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. view plainprint?2. /*3. * 前提条件,Parcel存在多个类型相同的对象,本例子以10个float对象说明:4. */5. public void readSameType() 6. Parcel parcel =Parcel.obtain() ;7. for (int i = 0; i + getParcelInfo();10. 11. /方法一 ,显示设置偏移量 12. int i = 0;13. int datasize = parcel.dataSize();14. while (i + getParcelInfo();18. i += 8; / double占用字节为 8byte 19. 20. / 方法二,由于对象的类型一致,我们可以直接利用readXXX()读取值会产生偏移量21. / parcel.setDataPosition(0);/22. / while(parcel.dataPosition() + getParcelInfo();25. / 26. 复制代码由于可能存在读取值的偏差,一个默认的取值规范为: 1、读取复杂对象时: 对象匹配时,返回当前偏移位置的该对象; 对象不匹配时,返回null对象 ; 2、读取简单对象时: 对象匹配时,返回当前偏移位置的该对象 ; 对象不匹配时,返回0; 下面,给出一张浅显的Parcel的存放空间图,希望大家在理解的同时,更能体味其中滋味。有点简单,求谅解。相信通过前面的介绍,你一定很了解了了Parcel的存储机制,下面给定一应用程序来实践。 1、布局文件如下:1. 2. 5. 7. 9. 11. 13. 14. 16. 18. 20. 21. 23. 26. 28. 30. 31. 33. 35. 37. 38. 40. 42. 复制代码2、配置文件如下:1. 2. 6. 7. 8. 9. 10. 11. 12. 13. 14. 复制代码3、程序主文件如下:1. public class MainActivity extends Activity implements OnClickListener 2. 3. private static String TAG = PARCELTEST;4. / Button ID5. private static int btIds = new int R.id.btWriteByte, R.id.btWriteInt,6. R.id.btReadDouble, R.id.btWriteString, R.id.btReadByte,7. R.id.btReadInt, R.id.btReadDouble, R.id.btReadString,8. R.id.btSameType ;9. / 每种类型的当前值10. private byte cur_byte = 1; / 每次总写入 false11. private int cur_int = 10; / 写入值 cur_int + ;12. private double cur_float = 100.0d; / 写入值 cur_float+ ;13. private String cur_str = QinJun - + cur_int; / 写入值 QinJun -+cur_int14. 15. private Parcel parcel = null;16. 17. Override18. public void onCreate(Bundle savedInstanceState) 19. super.onCreate(savedInstanceState);20. setContentView(R.layout.main);21. for (int i = 0; i + getParcelInfo();38. break;39. case R.id.btWriteInt:40. parcel.writeInt(cur_int);41. Log.i(TAG, after write int, - + getParcelInfo();42. break;43. case R.id.btWriteDouble:44. parcel.writeDouble(cur_float);45. Log.i(TAG, after write float, - + getParcelInfo();46. break;47. case R.id.btWriteString:48. parcel.writeString(cur_str);49. Log.i(TAG, after write String, - + getParcelInfo();50. break;51. case R.id.btReadByte:52. byte b = parcel.readByte();53. Log.i(TAG, read byte is= + b + , - + getParcelInfo()54. + String);55. break;56. case R.id.btReadInt:57. int i = parcel.readInt();58. Log.i(TAG, read int is= + i + , - + getParcelInfo();59. break;60. case R.id.btReadDouble:61. float f = parcel.readFloat();62. readSameType();63. Log.i(TAG, read float is= + f + , - + getParcelInfo();64. break;65. case R.id.btReadString:66. parcel.setDataPosition(0);67. String str = parcel.readString();68. Log.i(TAG, read float is= + str + , - + getParcelInfo();69. break;70. case R.id.btSameType:71. readSameType();72. break;73. default:74. break;75. 76. 77. 78. private String getParcelInfo() / 得到parcel的信息79. return dataSize = + parcel.dataSize() + , dataCapacity=80. + parcel.dataCapacity() + , dataPositon = 81. + parcel.dataPosition();82. 83. 84. /*85. * 前提条件,Parcel存在多个类型相同的对象,本例子以10个float对象说明:86. */87. public void readSameType() 88. 89. for (int i = 0; i + getParcelInfo();92. 93. /方法一 ,显示设置偏移量 94. int i = 0;95. int datasize = parcel.dataSize();96. while (i + getParcelInfo();100. i += 8; / double占用字节为 8b

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论