#### binder的工作机制
下面的代码是在IBookManager.aidl中,系统自动生成的IBookManager.java文件
~~~
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package com.ryg.chapter_2;
/*
* IBookManager它继承了IInterface这个接口,同时它自己也还是个接口,
* 所有可以在Binder中传输的接口都要继承IInterface接口。
*
* 首先,它声明了两个方法getBookList和addBook(在最后面),显然这就是我们在IBookManager.aidl中所声明的方法,
* 同时它还声明了两个整型的id(TRANSACTION_getBookList、TRANSACTION_addBook)分别用于标识这两个方法。
* 接着,它声明了一个内部类Stub,这个Stub就是一个Binder类,
* 当客户端和服务端都位于同一个进程时,方法调用不会走跨进程的transact过程,
* 而当两者位于不同进程时,方法调用需要走transact过程,
* 这个逻辑由Stub的内部代理类Proxy来完成。
*
*这个接口的核心就是内部类Stub和Stub的内部代理类Proxy
* */
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
/*
* 首先这个Stub,它是一个内部类,它继承了Binder,所以它是一个Binder,
* 同时Stub还实现了IBookManager中的方法。
* */
public static abstract class Stub extends android.os.Binder implements com.ryg.chapter_2.aidl.IBookManager {
//Binder的唯一标识符。 一般用于当前Binder的类名表示
private static final java.lang.String DESCRIPTOR = "com.ryg.chapter_2.aidl.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface (this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.ryg.chapter_2.aidl.IBookManager interface,
* generating a proxy if needed.
*/
/*
* 用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,
* 这种转换过程是区分进程的,
* 如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,
* 否则(即客户端和服务端不在同一个进程)返回的是系统封装后的Stub.proxy代理对象。
* */
public static com.ryg.chapter_2.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface (DESCRIPTOR);
// 同一进程
if (((iin != null) && (iin instanceof com.ryg.chapter_2.aidl.IBookManager))) {
return ((com.ryg.chapter_2.aidl.IBookManager) iin);
}
// 不同进程
return new com.ryg.chapter_2.aidl.IBookManager.Stub.Proxy (obj);
}
//此方法用于返回当前Binder对象,也就是内部类Stub。
@Override
public android.os.IBinder asBinder() {
return this;
}
/*
* 这个方法运行在服务端中的Binder线程池中,
* 当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。
* 该方法的原型是 public Boolean onTransact(int code,android.os.Parcel data,android.os.Parcel reply,int flags)
* 服务端通过code可以确定客户端所请求的目标方法是什么,
* 接着从data中取出目标方法所需的参数,
* 然后执行目标方法。
* 当目标方法执行完毕后,就向reply中写入返回值。
* 如果此方法返回false,那么客户端的请求会失败,因此我们可以利用这个特性来做权限验证。
* (毕竟也不希望随便一个进程都可以远程调用我们的服务)
* */
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString (DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface (DESCRIPTOR);
//这句才是调用了真正的执行过程呢
java.util.List<com.ryg.chapter_2.aidl.Book> _result = this.getBookList ();
reply.writeNoException ();
reply.writeTypedList (_result);
return true;//返回true表示调用成功
}
case TRANSACTION_addBook: {
data.enforceInterface (DESCRIPTOR);
com.ryg.chapter_2.aidl.Book _arg0;
if ((0 != data.readInt ())) {
_arg0 = com.ryg.chapter_2.aidl.Book.CREATOR.createFromParcel (data);
} else {
_arg0 = null;
}
//这句才是调用了真正的执行过程呢
this.addBook (_arg0);
reply.writeNoException ();
return true;
}
case TRANSACTION_registerListener: {
data.enforceInterface (DESCRIPTOR);
com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0;
_arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub.asInterface (data.readStrongBinder ());
this.registerListener (_arg0);
reply.writeNoException ();
return true;
}
case TRANSACTION_unregisterListener: {
data.enforceInterface (DESCRIPTOR);
com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0;
_arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub.asInterface (data.readStrongBinder ());
this.unregisterListener (_arg0);
reply.writeNoException ();
return true;
}
}
return super.onTransact (code, data, reply, flags);
}
//代理类Proxy。
private static class Proxy implements com.ryg.chapter_2.aidl.IBookManager {
/*
* 这个mRemote代表的就是目标对象角色,
* */
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/*
* 这个方法运行在客户端,
* 因为当客户端和服务端不在同一进程时,服务端返回代理类Proxy,所以客户端会通过Proxy调用到代理类的getBookList方法,
* 当客户端远程调用此方法时,它的内部实现是这样的:
* 首先创建该方法所需要的输入型Parcel对象_data、输出型Parcel对象_reply和返回值对象List,
* 然后把该方法的参数信息写入_data中,
* 接着调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起,
* 然后服务端的onTransact方法会被调用,直到RPC过程返回后,当前线程继续执行,
* 并从_reply中取出RPC过程的返回结果。
* 最后返回_reply中的数据。
* */
@Override
public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain ();
android.os.Parcel _reply = android.os.Parcel.obtain ();
java.util.List<com.ryg.chapter_2.aidl.Book> _result;
try {
_data.writeInterfaceToken (DESCRIPTOR);
mRemote.transact (Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException ();
_result = _reply.createTypedArrayList (com.ryg.chapter_2.aidl.Book.CREATOR);
} finally {
_reply.recycle ();
_data.recycle ();
}
return _result;
}
/**
* 这个方法运行在客户端,执行过程和getBookList一样,只是addBook没有返回值,
* 所以不需要从_reply中取出返回值
*/
@Override
public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain ();
android.os.Parcel _reply = android.os.Parcel.obtain ();
try {
_data.writeInterfaceToken (DESCRIPTOR);
if ((book != null)) {
_data.writeInt (1);
book.writeToParcel (_data, 0);
} else {
_data.writeInt (0);
}
mRemote.transact (Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException ();
} finally {
_reply.recycle ();
_data.recycle ();
}
}
@Override
public void registerListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain ();
android.os.Parcel _reply = android.os.Parcel.obtain ();
try {
_data.writeInterfaceToken (DESCRIPTOR);
_data.writeStrongBinder ((((listener != null)) ? (listener.asBinder ()) : (null)));
mRemote.transact (Stub.TRANSACTION_registerListener, _data, _reply, 0);
_reply.readException ();
} finally {
_reply.recycle ();
_data.recycle ();
}
}
@Override
public void unregisterListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain ();
android.os.Parcel _reply = android.os.Parcel.obtain ();
try {
_data.writeInterfaceToken (DESCRIPTOR);
_data.writeStrongBinder ((((listener != null)) ? (listener.asBinder ()) : (null)));
mRemote.transact (Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
_reply.readException ();
} finally {
_reply.recycle ();
_data.recycle ();
}
}
}
/*
* 用于标识方法的整型id。
* 它们用于在transact过程总客户端所请求的到底是哪个方法。
* */
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_registerListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_unregisterListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
}
/*
* 声明了在IBookManager.aidl中所声明的方法。
* 这里才是真正的方法声明。具体实现我们仍然没有看到呢。
* */
public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException;
public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException;
public void registerListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException;
public void unregisterListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException;
}
~~~
![](https://box.kancloud.cn/2016-05-29_574aa689ca354.png)
对于上图有网友这样理解,原文点击[这里](http://blog.csdn.net/zizidemenghanxiao/article/details/50341773)
对于自动生成的IBookManager.java文件,它是服务器端的代码。
当客户端向服务端发送连接请求时,
* 如果客户端和服务端在同一进程中,那么服务端就向客户端返回Stub这个Binder对象,
*
如果客户端和服务端在不同进程中,那么服务端就向客户端返回内部类Stub的内部代理类Proxy,然后客户端根据这个Proxy来调用Proxy内部的方法,这个Proxy内部含有服务端真正的Binder对象也就是那个内部类Stub,在客户端调用Proxy内部的方法也就会导致调用Stub的transact方法,而Stub的transact方法又会回调它自己的onTransact方法,onTransact方法是在服务端运行的,而transact方法是在客户端调用的,这样就实现了客户端调用服务端的方法了。当然这所有的传递过程也少不了Parcel这个数据包的协助。
* * * * *
> **Binder一个很重要的作用是:将客户端的请求参数通过Parcel包装后传到远程服务端,远程服务端解析数据并执行对应的操作,同时客户端线程挂起,当服务端方法执行完毕后,再将返回结果写入到另外一个Parcel中并将其通过Binder传回到客户端,客户端接收到返回数据的Parcel后,Binder会解析数据包中的内容并将原始结果返回给客户端,至此,整个Binder的工作过程就完成了。由此可见,Binder更像一个数据通道,Parcel对象就在这个通道中跨进程传输,至于双方如何通信,这并不负责,只需要双方按照约定好的规范去打包和解包数据即可。**
* * * * *
- 前言
- 第一章Activity的生命周期和启动模式
- 1.1 Activity生命周期全面分析
- 1.2 Activity的启动模式
- 1.3 IntentFilter的匹配规则
- 第二章IPC
- 转 chapter IPC
- 转IPC1
- 转IPC2
- Binder讲解
- binder
- Messenger
- 一、Android IPC简介
- 二、Android中的多进程模式
- 三、IPC基础概念介绍
- 四、Android中的IPC方式
- 五、Binder连接池
- 第三章
- 第九章四大组件的工作过程
- 第十章
- 第13章 综合技术
- 使用CrashHandler 来获取应用的crash 信息
- 使用Multidex来解决方法数越界
- Android的动态加载技术