android parcel.cpp 函数指针,Parcel_进程间数据传递

Parcel,即打包。为何须要打包呢?是为了序列化。java

若是要在进程之间传递一个整数,很简单,直接传就好了;若是要传一个字符串,就稍微复杂了点:需先分配一块能够容纳字符串的内存,而后将字符串复制到内存中,再传递(新手可能问:为啥不直接把字符串的引用传过去呢?学过C/C++的地球人都知道:进程有本身的内存地址空间,一个进程中的1000地址可能在另外一个进程中是100000,Java对象的引用跟本上仍是内存地址);再若是要传递一个类的实例呢?也是先为实例分配内存,而后复制一份再传递能够吗?我认为不能够,我至少能够找到一个理由:类中成员除了属性还有方法,即便属性能完整传过去,但方法呢?方法是独立于类对象存在的,因此到另外一个进程中再引用同一个方法就要出错了,仍是由于独立地址空间的缘由。android

Android开发中,常常在Activity之间传递数据,而根据android的设计架构,即便同一个应用程序中的Activity都不必定运行在同一个进程中,因此处理数据传递时你不能假设两个Activity都运行于同一进程中,那么只能按进程间传递数据来处理,使之具备最普遍的适应性。服务器

如何在进程之间传递类对象呢?简单来讲能够这样作:在进程A中把类中的非默认值的属性和类的惟一标志打成包(这就叫序列化),把这个包传递到进程B,进程B接收到包后,根据类的惟一标志把类建立出来,而后把传来的属性更新到类对象中,这样进程A和进程B中就包含了两个彻底同样的类对象。架构

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

ide

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

// code :是请求的ID号

// data :客户端请求发送的参数

// reply:服务器端返回的结果

// flags:一些额外的标识,如FLAG_ONEWAY等,一般为0.

virtualstatus_t    onTransact( uint32_t code,constParcel& data,   Parcel* reply,   uint32_t flags = 0);

从中咱们能够看到Parcel的重要性。post

经常使用方法介绍:性能

obtain()                          得到一个新的parcel ,至关于new一个对象网站

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

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

dataPosition()                 得到当前parcel对象的偏移量(相似于文件流指针的偏移量)

setDataPosition()           设置偏移量

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

writeInt(int)                     写入一个整数

writeFloat(float)              写入一个浮点数

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

writeString(string)           写入一个字符串

固然,还有更多的writeXXX()方法,与之对应的就是readXXX()。

事实上,咱们能够显式的经过setDataPostion(int postion) 来直接操做咱们欲读取数据时的偏移量。毫无疑问,你能够设置任何偏移量,但所读取的值是类型可能有误。所以显示设置偏移量读取值的时候,须要当心。

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

此时的datapostion=4,若是咱们想读取23,简单的经过readInt()是不行的,只能获得0。这时咱们只能经过

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

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

巧用setDataPosition()方法,当咱们的Parcel对象中只存在某一类型时,咱们就能够经过这个方法来快速的读取

全部值。具体方法以下:

/**

* 前提条件,Parcel存在多个类型相同的对象,本例子以10个float对象说明:

*/

publicvoidreadSameType() {

Parcel parcel =Parcel.obtain() ;

for(inti =0; i <10; i++) {

parcel.writeDouble(i);

Log.i(TAG, "write double ----> "+ getParcelInfo());

}

//方法一 ,显式设置偏移量

inti =0;

intdatasize = parcel.dataSize();

while(i 

parcel.setDataPosition(i);

doublefvalue = parcel.readDouble();

Log.i(TAG, " read double is="+ fvalue +", --->"+ getParcelInfo());

i += 8;// double占用字节为 8byte

}

//      方法二,因为对象的类型一致,咱们能够直接利用readXXX()读取值会产生偏移量

//      parcel.setDataPosition(0)  ;  //

//      while(parcel.dataPosition()

//          double fvalue = parcel.readDouble();

//          Log.i(TAG, " read double is=" + fvalue + ", --->" + getParcelInfo());

//      }

}

因为可能存在读取值的误差,一个默认的取值规范为:

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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
com.miui.frameworks.servicestests (1 Test) [1/1] com.android.server.location.gnss.hal.Gpo4ClientTest#init: FAILED (141ms) STACKTRACE: java.lang.SecurityException: uid 10289 does not have android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION. at android.os.Parcel.createExceptionOrNull(Parcel.java:3011) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at android.location.ILocationManager$Stub$Proxy.registerLocationListener(ILocationManager.java:1291) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1551) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1234) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1199) at com.android.server.location.gnss.hal.Gpo4Client.registerPassiveLocationUpdates(Gpo4Client.java:198) at com.android.server.location.gnss.hal.Gpo4Client.init(Gpo4Client.java:78) at com.android.server.location.gnss.hal.Gpo4ClientTest.init(Gpo4ClientTest.java:209) ... 8 trimmed Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.location.LocationPermissions.enforceLocationPermission(LocationPermissions.java:116) at com.android.server.location.LocationManagerService.registerLocationListener(LocationManagerService.java:786) at android.location.ILocationManager$Stub.onTransact(ILocationManager.java:582) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1249)
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值