Android中的Parcel是什么 
Parcel,翻译过来是“打包”的意思。打包干什么呢?是为了序列化。

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

    Android开发中,很经常在各activity之间传递数据,而跟据Android的设计架构,即使同一个程序中的Activity都不一定运行在同一个进程中,所以处理数据传递时你不能老假设两个activity都运行于同一进程,那么只能按进程间传递数据来处理,使之具有最广泛的适应性。

  那么到底如何在进程之间传递类对象呢?简单来说可以这样做:在进程A中把类中的非默认值的属性和类的唯一标志打成包(这就叫序列化),把这个包传递到 进程B,进程B接收到包后,跟据类的唯一标志把类创建出来,然后把传来的属性更新到类对象中,这样进程A和进程B中就包含了两个完全一样的类对象。


Android开发:什么是IBinder 
上回书简单描述了进程间传递类对象的原理,这回在讲Parcel之前,先要讲一个东西:IBinder。 
IBinder是什么呢?首先要明白,Android的远程调用(就是跨进程调用)就是通过IBinder实现的,下面是对android开发文档的翻译。 
IBinder是远程对象的基本接口,是为高性能而设计的轻量级远程调用机制的核心部分。但它不仅用于远程调用,也用于进程内调用。这个接口定义了与远程对象交互的协议。不要直接实现这个接口,而应该从Binder派生。 
IBinder的主要API是transact(),与它对应另一方法是Binder.onTransact()。第一个方法使你可以向远端的IBinder对象发送发出调用,第二个方法使你自己的远程对象能够响应接收到的调用。IBinder的API都是同步执行的,比如transact()直到对方的Binder.onTransact()方法调用完成后才返回。调用发生在进程内时无疑是这样的,而在进程间时,在IPC的帮助下,也是同样的效果。 
通过transact()发送的数据是Parcel,Parcel是一种一般的缓冲区,除了有数据外还带有一些描述它内容的元数据。元数据用于管理IBinder对象的引用,这样就能在缓冲区从一个进程移动到另一个进程时保存这些引用。这样就保证了当一个IBinder被写入到Parcel并发送到另一个进程中,如果另一个进程把同一个IBinder的引用回发到原来的进程,那么这个原来的进程就能接收到发出的那个IBinder的引用。这种机制使IBinder和Binder像唯一标志符那样在进程间管理。(总结:像内部变量一样,调用的是同一个变量。)
系统为每个进程维护一个存放交互线程的线程池。这些交互线程用于派送所有从另外进程发来的IPC调用。例如:当一个IPC从进程A发到进程B,A中那个发 出调用的线程(这个应该不在线程池中)就阻塞在transact()中了。进程B中的交互线程池中的一个线程接收了这个调用,它调用 Binder.onTransact(),完成后用一个Parcel来做为结果返回。然后进程A中的那个等待的线程在收到返回的Parcel后得以继续执
行。实际上,另一个进程看起来就像是当前进程的一个线程,但不是当前进程创建的。(过程!重点!)
Binder机制还支持进程间的递归调用。例如,进程A执行自己的IBinder的transact()调用进程B的Binder,而进程B在其 Binder.onTransact()中又用transact()向进程A发起调用,那么进程A在等待它发出的调用返回的同时,还会用 Binder.onTransact()响应进程B的transact()。

总之Binder造成的结果就是让我们感觉到跨进程的调用与进程内的调用没什 么区别。 
当操作远程对象时,你经常需要查看它们是否有效,有三种方法可以使用: 
1 transact()方法将在IBinder所在的进程不存在时抛出RemoteException异常。 
2 如果目标进程不存在,那么调用pingBinder()时返回false。 
3 可以用linkToDeath()方法向IBinder注册一个IBinder.DeathRecipient,在IBinder代表的进程退出时被调用。

要实现IBinder来支持远程调用,应从Binder类派生一个类。Binder实现了IBinder接口。但是一般不需要直接实现此类,而是跟据你的 需要由开发包中的工具生成,这个工具叫aidl。你通过aidl语言定义远程对象的方法,然后用aidl工具生成Binder的派生类,然后就可使用之。 然而,可是,但是,当然,你也可以直接从Binder类派生以实现自定义的RPC(Remote Procedure Call)调用,或只是实例化一个原始的Binder对象直接作为进程间共享的令牌 来使用。


Android开发:什么是Parcel(2) 
上回书解释了IBinder,这回详细解释一下Parcel,以下是对android sdk 文档的翻议: 
Parcel是一个容器,它主要用于存储序列化数据,然后可以通过Binder在进程间传递这些数据(要了解为什么要序列化,请参 考:http://blog.csdn.net/nkmnkm/archive/2011/05/28/6451699.aspx)。

1、Parcel可以包 含原始数据类型(用各种对应的方法写入,比如writeInt(),writeFloat()等)

2、可以包含Parcelable对象,它还包含了一个活 动的IBinder对象的引用,这个引用导致另一端接收到一个指向这个IBinder的代理IBinder。 

注:Parcel不是一般目的的序列化机制。这个类被设计用于高性能的IPC传输。因此不适合把Parcel写入永久化存储中,因为Parcel中的数据类型的实现的改变会导致旧版的数据不可读。

  Parcel的一坨一坨的API用于解决不同类型数据的读写。这些函数们主要有六种类型。

1原始类

这类方法们主要读写原始数据类型。它们是:writeByte(byte), readByte(), writeDouble(double), readDouble(), writeFloat(float), readFloat(), writeInt(int), readInt(), writeLong(long), readLong(), writeString(String), readString(). 大多数其它数据的操作都是基于这些方法。

2原始数组类

这类方法用于读写原始数据组成的数组。在向数组写数据时先写入数组的长度再写入数据。读数组的方法可以将数据读到已存在的数组中,也可以创建并返回一个新数组。它们是:

writeBooleanArray(boolean[]), readBooleanArray(boolean[]), createBooleanArray() 
writeByteArray(byte[]), writeByteArray(byte[], int, int), readByteArray(byte[]), createByteArray() 
writeCharArray(char[]), readCharArray(char[]), createCharArray() 
writeDoubleArray(double[]), readDoubleArray(double[]), createDoubleArray() 
writeFloatArray(float[]), readFloatArray(float[]), createFloatArray() 
writeIntArray(int[]), readIntArray(int[]), createIntArray() 
writeLongArray(long[]), readLongArray(long[]), createLongArray() 
writeStringArray(String[]), readStringArray(String[]), createStringArray(). 
writeSparseBooleanArray(SparseBooleanArray), readSparseBooleanArray(). 
3 Parcelable类 
Parcelable为对象从Parcel中读写自己提供了极其高效的协议。你可以使用直接的方法 writeParcelable(Parcelable, int) 和 readParcelable(ClassLoader) 或 writeParcelableArray(T[], int) and readParcelableArray(ClassLoader) 进行读写。这些方法们把类的信息和数据都写入Parcel,以使将来能使用合适的类装载器重新构造类的实例。

还有一些方法提供了更高效的操作Parcelable们的途径,它们是:writeTypedArray(T[], int), writeTypedList(List), readTypedArray(T[], Parcelable.Creator) and readTypedList(List, Parcelable.Creator)。这些方法不会写入类的信息,取而代之的是:读取时必须能知道数据属于哪个类并传入正确的 Parcelable.Creator来创建对象而不是直接构造新对象。(更加高效的读写单个Parcelable对象的方法是:直接调用
Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())

4 Bundles类

Bundles是一种类型安全的Map型容器,可用于存储任何不同类型的数据。它具有很多对讀写数据的性能优化,并且它的类型安全机制避免了当把它的数据封送到Parcel中时由于类型错误引起的BUG的调试的麻烦,可以使用的方法为: writeBundle(Bundle), readBundle(), and readBundle(ClassLoader)。

5 活动对象类

Parcel的一个非同寻常的特性是读写活对象的能力。对于活动对象,它们的内容实际上并没有写入,而是仅写入了一个令牌来引用这个对象。当从Parcel中读取这个对象时,你不会获取一个新的对象实例,而是直接得到那个写入的对象。有两种活动对象可操作:

Binder对象。它是Android跨进程通讯的基础。这种对象可被写入Parcel,并在读取时你将得到原始的对象或一个代理对象(可以想象:在进程内时得到原始的对象,在进程间时得到代理对象)。可以使用的方法们是: writeStrongBinder(IBinder), writeStrongInterface(IInterface), readStrongBinder(), writeBinderArray(IBinder[]), readBinderArray(IBinder[]), createBinderArray(),
writeBinderList(List), readBinderList(List), createBinderArrayList()。

FileDescriptor对象。它代表了原始的Linux文件描述符,它可以被写入Parcel并在读取时返回一个 ParcelFileDescriptor对象用于操作原始的文件描述符。ParcelFileDescriptor是原始描述符的一个复制:对象和fd 不同,但是都操作于同一文件流,使用同一个文件位置指针,等等。可以使用的方法 是:writeFileDescriptor(FileDescriptor), readFileDescriptor()。

6无类型容器类

    一类final方法,用于读写标准的java容器类。这些方法们是:writeArray(Object[]), readArray(ClassLoader), writeList(List), readList(List, ClassLoader), readArrayList(ClassLoader), writeMap(Map), readMap(Map, ClassLoader), writeSparseArray(SparseArray), readSparseArray(ClassLoader)。

什么是Pending intent 
Pending描述了一个Intent和intent的动作。这个类的实例是用getActivity(Context,int,Intent,int) 方法和getBroadcast(Context,int,Intent,int)和 getService(Context,int,Intent,int)方法创建的。创建出的pending intent可以交给其它程序,于是它们可以在以后的某个时间以你的名义执行intent中所描述的动作。
 

通过给于一个PendingIntent,你可以使其它程序像你自己一样执行你所指定的操作(具有相同的权限和身份)。所以,你需要小心的创建 PendingIntent:通常,你最基本的应该明确设置你的相关组件的名字,以保证将来intent是被发送给它而不是其它地方。
 

一个PendingIntent本是只是简单地引用一个由系统维护的一个令牌,这个令牌描述了用于取得PendingIntent的原始数据。这表示即使 拥有这个PendingIntent的进程关闭了,但这个PendingIntent对于那些收到它的进程依然有效。如果创建这个 PendingIntent的程序又重新运行并重新获取同一个类型的PendingIntent(相同的操作,action,数据,类型和组件以及相同的 标志),那么获取的还是这个PendingIntent,并且这个程序可以用cancel()来删除这个PendingIntent。

android binder理解的更多相关文章

  1. Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. 理解 Android Binder 机制(一):驱动篇

    Binder的实现是比较复杂的,想要完全弄明白是怎么一回事,并不是一件容易的事情. 这里面牵涉到好几个层次,每一层都有一些模块和机制需要理解.这部分内容预计会分为三篇文章来讲解.本文是第一篇,首先会对 ...

  3. Android Binder机制详解:手写IPC通信

    想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...

  4. ANDROID BINDER机制浅析

    Binder是Android上一种IPC机制,重要且较难理解.由于Linux上标准IPC在灵活和可靠性存在一定不足,Google基于OpenBinder的设计和构想实现了Binder. 本文只简单介绍 ...

  5. (原创)Android Binder设计与实现 - 实现篇(1)

    本文属于原创作品,转载请注明出处并放于明显位置,原文地址:http://www.cnblogs.com/albert1017/p/3849585.html 前言 在学习Android的Binder机制 ...

  6. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  7. android binder 基础实例及解析(一)【转】

    本文转载自:http://blog.csdn.net/newchenxf/article/details/49359283#insertcode 原文网址(转载请注明出处): http://blog. ...

  8. Android binder流程简图

    前段时间因为一个bug,研究了一下android binder的大概流程,方便自己理解画了一个框图. 粗点线箭头是继承关系,细实线箭头是调用关系.

  9. Android Binder机制彻底梳理二

    根据AIDL了解整体调用流程[重点分析AIDL流程]: 在上一次https://www.cnblogs.com/webor2006/p/11741743.html中我们已经对Android Binde ...

随机推荐

  1. C++笔记--1

    一.namespace 命名空间 //定义一个命名空间 namespace spaceA { ; } int main(void) { //调用方式一 using namespace spaceA; ...

  2. Go 语言数组

    Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0, number ...

  3. Docker的名字空间

    名字空间是 Linux 内核一个强大的特性.每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样.名字空间保证了容器之间彼此互不影响. pid 名字空间 不同用户的进程就是 ...

  4. Template基础

    模板系统的介绍 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now ...

  5. iOS开源加密相册Agony的实现(三)

    简介 虽然目前市面上有一些不错的加密相册App,但不是内置广告,就是对上传的张数有所限制.本文介绍了一个加密相册的制作过程,该加密相册将包括多密码(输入不同的密码即可访问不同的空间,可掩人耳目).Wi ...

  6. 热烈庆祝自已厉精13年开发的 DB查询分析器 7.01(最新版本) 在中关村在线本月获得近6000次的下载量

    中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本 DB 查询分析器.英文版本DB Query Analyzer.它 ...

  7. CDH集群安装&测试总结

    0.绪论 之前完全没有接触过大数据相关的东西,都是书上啊,媒体上各种吹嘘啊,我对大数据,集群啊,分布式计算等等概念真是高山仰止,充满了仰望之情,觉得这些东西是这样的: 当我搭建的过程中,发现这些东西是 ...

  8. FORM开发之键性弹性域开发

    1.创建表时带有键弹性域字段 SUMMARY_FLAG VARCHAR2(1) , /* 必须有此字段 */ ENABLED_FLAG VARCHAR2(1) , /* 必须有此字段 */ START ...

  9. @property的参数

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51353580 本文出自:[openXu的博客] 参数类别 参数 说明 原子性 atomic ...

  10. 1.物理系统PhysicsWorld,RayCast

     1 3.0物理系统PhysicsWorld T07PhysicsWorld.h #ifndef __T07PhysicsWorld_H__ #define __T07PhysicsWorld_H ...