1.What?
Binder是什么?Binder是Android系统中的一种进程间通讯方式,因为平时开发App一般不涉及到这方面的东西,所以一般开发者了解比较少,今天我们来学习一下Binder机制。
先来看Google给Binder类的描述:
Base class for a remotable object, the core part of a lightweight remote procedure call mechanism defined by
IBinder
. This class is an implementation of IBinder that provides standard local implementation of such an object.Most developers will not implement this class directly, instead using the aidl tool to describe the desired interface, having it generate the appropriate Binder subclass. You can, however, derive directly from Binder to implement your own custom RPC protocol or simply instantiate a raw Binder object directly to use as a token that can be shared across processes.
This class is just a basic IPC primitive; it has no impact on an application’s lifecycle, and is valid only as long as the process that created it continues to run. To use this correctly, you must be doing so within the context of a top-level application component (a
Service
,Activity
, orContentProvider
) that lets the system know your process should remain running.You must keep in mind the situations in which your process could go away, and thus require that you later re-create a new Binder and re-attach it when the process starts again. For example, if you are using this within an
Activity
, your activity’s process may be killed any time the activity is not started; if the activity is later re-created you will need to create a new Binder and hand it back to the correct place again; you need to be aware that your process may be started for another reason (for example to receive a broadcast) that will not involve re-creating the activity and thus run its code to create a new Binder.
Binder是远程对象的基类,它的核心部分:轻量级远程过程调用链由IBinder定义,这个类是IBinder的实现,提供标准本地实现。
大部分开发者不需要直接实现这个类,作为代替使用AIDL工具来描述想要的接口,生成合适的Binder的子类。
你可以直接从Binder获得实现你自己的远程过程调用协议或者是简单的取得一个Binder实例来作为一个可以被跨进程共享的标记来使用。
Binder这个类只是一个原始的IPC方式,它对App的生命周期没有影响,它从进程创建并运行它起才开始生效。为了正确的使用它,你必须要在顶层App组件环境里使用来让系统知道你的进程应该保持运行。
你一定要记住有些情况下你的进程会go away,这就要求你在之后重新创建一个新的Binder并且重新attach它当这个进程再次启动。举个例子,如果你在Activity里使用它,当这个activity没有启动时,你的activity所在的进程可能在任何时间被杀掉,如果这个activity之后被重建,你需要创建一个新的Binder并把它放到正确的位置,你要注意你的进程可能因为其它的原因而启动(例如接收广播),这种情况下不会重新创建activity,这就需要你来自己处理创建一个新的Binder。
这一段说了些什么呢?简单的总结一下:
Binder类只是一个简单的IPC方式,我们需要自己实现我们希望的逻辑,Binder可以简单的作为一个进程间共享的变量来使用,也可以作为一套复杂的协议来处理,这取决于你怎么实现它。作为App开发者,通常情况下我们可以使用AIDL工具来帮助我们生成Binder。
使用Binder时要注意进程的变化情况和Binder所在的环境,进程有可能意外被杀死或者唤起,这就需要你去做对应的处理。
接下来来看看IBinder这个类的描述:
Base interface for a remotable object, the core part of a lightweight remote procedure call mechanism designed for high performance when performing in-process and cross-process calls. This interface describes the abstract protocol for interacting with a remotable object. Do not implement this interface directly, instead extend from
Binder
.The key IBinder API is
transact()
matched byBinder.onTransact()
. These methods allow you to send a call to an IBinder object and receive a call coming in to a Binder object, respectively. This transaction API is synchronous, such that a call totransact()
does not return until the target has returned fromBinder.onTransact()
; this is the expected behavior when calling an object that exists in the local process, and the underlying inter-process communication (IPC) mechanism ensures that these same semantics apply when going across processes.The data sent through transact() is a
Parcel
, a generic buffer of data that also maintains some meta-data about its contents. The meta data is used to manage IBinder object references in the buffer, so that those references can be maintained as the buffer moves across processes. This mechanism ensures that when an IBinder is written into a Parcel and sent to another process, if that other process sends a reference to that same IBinder back to the original process, then the original process will receive the same IBinder object back. These semantics allow IBinder/Binder objects to be used as a unique identity (to serve as a token or for other purposes) that can be managed across processes.The system maintains a pool of transaction threads in each process that it runs in. These threads are used to dispatch all IPCs coming in from other processes. For example, when an IPC is made from process A to process B, the calling thread in A blocks in transact() as it sends the transaction to process B. The next available pool thread in B receives the incoming transaction, calls Binder.onTransact() on the target object, and replies with the result Parcel. Upon receiving its result, the thread in process A returns to allow its execution to continue. In effect, other processes appear to use as additional threads that you did not create executing in your own process.
The Binder system also supports recursion across processes. For example if process A performs a transaction to process B, and process B while handling that transaction calls transact() on an IBinder that is implemented in A, then the thread in A that is currently waiting for the original transaction to finish will take care of calling Binder.onTransact() on the object being called by B. This ensures that the recursion semantics when calling remote binder object are the same as when calling local objects.
When working with remote objects, you often want to find out when they are no longer valid. There are three ways this can be determined:
- The
transact()
method will throw aRemoteException
exception if you try to call it on an IBinder whose process no longer exists.- The
pingBinder()
method can be called, and will return false if the remote process no longer exists.- The
linkToDeath()
method can be used to register aIBinder.DeathRecipient
with the IBinder, which will be called when its containing process goes away.
IBinder是为远程对象提供的基本接口,它是高效执行进程间和跨进程调用的轻量级远程调用机制的核心部分。这个接口描述了与远程对象交互的抽象协议。不要直接实现这个接口,而应该继承Binder来使用它。
IBinder的关键API是和Binder.onTransact
匹配的transact
方法。这些方法分别允许你传递一个调用给IBinder对象和接受来自Binder对象的调用。这俩方法都是同步的,即一直堵塞直到返回结果,