#### 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;
}
~~~

對于上圖有網友這樣理解,原文點擊[這里](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的動態加載技術