<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #### 2.3.3 Binder Binder是一個很深入的話題,筆者也看過一些別人寫的Binder相關的文章,發現很少有人能把它介紹清楚,不是深入代碼細節不能自拔,就是長篇大論不知所云,看完后都是暈暈的感覺。所以,本節筆者不打算深入探討Binder的底層細節,因為Binder太復雜了。本節的側重點是介紹Binder的使用以及上層原理,為接下來的幾節內容做鋪墊。 * 直觀來說,Binder是Android中的一個類,它繼承了IBinder接口。 * 從IPC角度來說,Binder是Android中的一種跨進程通信方式,Binder還可以理解為一種虛擬的物理設備,它的設備驅動是/dev/binder,該通信方式在Linux中沒有; * 從Android Framework角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager,等等)和相應ManagerService的橋梁; * 從Android應用層來說,Binder是客戶端和服務端進行通信的媒介,當bindService的時候,服務端會返回一個包含了服務端業務調用的Binder對象,通過這個Binder對象,客戶端就可以獲取服務端提供的服務或者數據,這里的服務包括普通服務和基于AIDL的服務。 :-: ![](https://img.kancloud.cn/03/d5/03d5b81e6d32b825b2a2fea4a6babce9_671x436.jpg) Binder流程圖 **Android開發中,Binder主要用在Service中,包括AIDL和Messenger,其中普通Service中的Binder不涉及進程間通信,所以較為簡單,無法觸及Binder的核心,而Messenger的底層其實是AIDL,Messenger、AIDL、ContentProvider的底層實現都Binder,所以這里選擇用AIDL來分析Binder的工作機制**。 為了分析Binder的工作機制,我們需要新建一個AIDL示例,SDK會自動為我們生產AIDL所對應的Binder類,然后我們就可以分析Binder的工作過程。還是采用本章開始時用的例子,新建Java包com.ryg.chapter_2.aidl,然后新建三個文件Book.java、Book.aidl和IBookManager.aidl,代碼如下所示。 **Book.java** ``` package com.ryg.chapter_2.aidl; import android.os.Parcel; import android.os.Parcelable; public class Book implements Parcelable { public int bookId; public String bookName; public Book() { } public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; } public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt(bookId); out.writeString(bookName); } public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() { public Book createFromParcel(Parcel in) { return new Book(in); } public Book[] newArray(int size) { return new Book[size]; } }; private Book(Parcel in) { bookId = in.readInt(); bookName = in.readString(); } @Override public String toString() { return String.format("[bookId:%s, bookName:%s]", bookId, bookName); } } ``` **Book.aidl** ``` package com.ryg.chapter_2.aidl; parcelable Book; ``` **IBookManager.aidl** ``` package com.ryg.chapter_2.aidl; import com.ryg.chapter_2.aidl.Book; interface IBookManager { List<Book> getBookList(); void addBook(in Book book); } ``` 上面三個文件中, * Book.java是一個表示圖書信息的類,它實現了Parcelable接口。 * Book.aidl是Book類在AIDL中的聲明。 * IBookManager.aidl是我們定義的一個接口,里面有兩個方法:getBookList和addBook,其中getBookList用于從遠程服務端獲取圖書列表,而addBook用于往圖書列表中添加一本書,當然這兩個方法主要是示例用,不一定要有實際意義。 我們可以看到,**盡管Book類已經和IBookManager位于相同的包中,但是在IBookManager中仍然要導入Book類,這就是AIDL的特殊之處**。 下面我們先看一下系統為IBookManager.aidl生產的Binder類,在gen目錄下的com.ryg.chapter_2.aidl包中有一個IBookManager.java的類,這就是我們要找的類。接下來我們需要根據這個系統生成的Binder類來分析Binder的工作原理,代碼如下: **服務器端的代碼**: ``` /** *This file is auto-generated. DO NOT MODIFY. *Original file: E:\\workspace\\Chapter_2\\src\\com\\ryg\\chapter_2\\aidl\\IBookManager.aidl */ package com.ryg.chapter_2.aidl; public interface IBookManager extends android.os.IInterface { /* Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ryg.chapter_2.aidl.IBookManager { 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. */ 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); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags) throws android.os.Remote-Exception { 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; } 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.create- FromParcel(data); } else { _arg0 = null; } this.addBook(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.ryg.chapter_2.aidl.IBookManager { 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; } @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; } @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(); } } } static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } 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; } ``` :-: ![](https://img.kancloud.cn/50/46/50466e29beae2ba7e510ef2913211f0b_829x703.png) 系統為IBookManager.aidl自動生成的gen目錄下的IBookManager.java類的結構圖 >[info]注意,上圖其中的某些方法并不是該小章節的方法,而是整個第2章binder知識所命名的方法 上述代碼是系統生成的,為了方便查看筆者稍微做了一下格式上的調整。 在gen目錄下,可以看到根據IBookManager.aidl系統為我們生成了**IBookManager.java這個類,它繼承了IInterface這個接口,同時它自己也還是個接口,所有可以在Binder中傳輸的接口都需要繼承IInterface接口**。 這個類剛開始看起來邏輯混亂,但是實際上還是很清晰的,通過它我們可以清楚地了解到Binder的工作機制。 這個類的結構其實很簡單, * 首先,它聲明了兩個方法getBookList和addBook,顯然這就是我們在IBookManager.aidl中所聲明的方法,同時它還聲明了兩個整型的id(`TRANSACTION_getBookList `和`TRANSACTION_addBook`)分別用于標識這兩個方法,這兩個id用于標識在transact過程中客戶端所請求的到底是哪個方法。 * 接著,**它聲明了一個內部類Stub,這個Stub就是一個Binder類,當客戶端和服務端都位于同一個進程時,方法調用,不會走跨進程的transact過程,而當兩者位于不同進程時,方法調用,需要走transact過程,這個邏輯由Stub的內部代理類Proxy來完成**。這么來看,IBookManager這個接口的確很簡單,但是我們也應該認識到,這個**接口的核心實現就是它的內部類Stub和Stub的內部代理類Proxy**, 完整的代碼(整個第2章的)如下圖所示(idea編輯器自動生成的), ![](https://img.kancloud.cn/53/01/5301f20d4a21f0bdfb039464820449a2_720x396.png) ~~~ /* * This file is auto-generated. DO NOT MODIFY. * Original file: E:\\AndroidStudioProjects\\AndroidDevelopArtistic\\Chapter_2\\src\\main\\aidl * \\com\\ryg\\chapter_2\\aidl\\IBookManager.aidl */ package com.ryg.chapter_2.aidl; public interface IBookManager extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ryg.chapter_2.aidl.IBookManager { 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. */ 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); } @Override public android.os.IBinder asBinder() { return this; } @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; } 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); } private static class Proxy implements com.ryg.chapter_2.aidl.IBookManager { 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; } @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; } @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(); } } } 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); } 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://img.kancloud.cn/50/46/50466e29beae2ba7e510ef2913211f0b_829x703.png) 系統為IBookManager.aidl自動生成的gen目錄下的IBookManager.java類的結構圖 下面詳細介紹針對這兩個類的每個方法的含義。 * **DESCRIPTOR** **Binder的唯一標識,一般用當前Binder的類名表示**,比如本例中的“com.ryg. chapter_2.aidl.IBookManager”。 * **asInterface(android.os.IBinder obj)** **用于將服務端的Binder對象轉換成客戶端所需的AIDL接口類型的對象,這種轉換過程是區分進程的,如果客戶端和服務端位于同一進程,那么此方法返回的就是服務端的Stub對象本身,否則返回的是系統封裝后的Stub.proxy對象**。 * **asBinder** 此方法用于返回當前Binder對象。 * **onTransact** * **這個方法運行在服務端中的Binder線程池中**,執行過程:**當客戶端發起跨進程請求時,遠程請求會通過系統底層封裝后交由此方法來處理。該方法的原型為public Boolean onTransact (int code, android.os.Parcel data, android.os.Parcel reply, int flags)。服務端通過code可以確定客戶端所請求的目標方法是什么,接著從data中取出目標方法所需的參數(如果目標方法有參數的話),然后執行目標方法。當目標方法執行完畢后,就向reply中寫入返回值(如果目標方法有返回值的話), onTransact方法的執行過程就是這樣的**。 需要注意的是,**如果此方法返回false,那么客戶端的請求會失敗,因此我們可以利用這個特性來做權限驗證,畢竟我們也不希望隨便一個進程都能遠程調用我們的服務**。 * **Proxy#getBookList** ~~~ @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; } ~~~ 這個方法**運行在客戶端**,當客戶端遠程調用此方法時,它的內部實現是這樣的:首先創建該方法所需要的輸入型Parcel對象_data、輸出型Parcel對象_reply和返回值對象List;然后把該方法的參數信息寫入_data中(如果有參數的話);接著調用transact方法來發起**RPC(遠程過程調用**)請求,同時當前線程掛起;然后服務端的onTransact方法會被調用,直到RPC過程返回后,當前線程繼續執行,并從_reply中取出RPC過程的返回結果;最后返回_reply中的數據。 * **Proxy#addBook** 這個方法**運行在客戶端**,它的執行過程和getBookList是一樣的,addBook沒有返回值,所以它不需要從_reply中取出返回值。 通過上面的分析,讀者應該已經了解了Binder的工作機制,但是有兩點還是需要額外說明一下: 1. 首先,當客戶端發起遠程請求時,由于當前線程會被掛起直至服務端進程返回數據,所以如果一個遠程方法是很耗時的,那么**不能在UI線程中發起此遠程請求**; 2. 其次,由于服務端的Binder方法運行在Binder的線程池中,所以**Binder方法不管是否耗時都應該采用同步的方式去實現,因為它已經運行在一個線程中了**。 為了更好地說明Binder,下面給出一個Binder的工作機制圖,如圖2-5所示。從下圖來看,**binder更像是一個數據通道**。 :-: ![](https://img.kancloud.cn/d4/e7/d4e7489a2008bd926464351c901dd451_1361x513.png) 圖2-5 Binder的工作機制 從上述分析過程來看,我們**完全可以不提供AIDL文件即可實現Binder,之所以提供AIDL文件,是為了方便系統為我們生成代碼**。 系統根據AIDL文件生成Java文件的格式是固定的,我們可以拋開AIDL文件直接寫一個Binder出來,接下來我們就介紹**如何手動寫一個Binder**。還是上面的例子,但是這次我們不提供AIDL文件。參考上面系統自動生成的IBookManager.java這個類的代碼,可以發現這個類是相當有規律的,根據它的特點,我們完全可以自己寫一個和它一模一樣的類出來,然后這個不借助AIDL文件的Binder就完成了。但是我們發現系統生成的類看起來結構不清晰,我們想試著對它進行結構上的調整,**可以發現這個類主要由兩部分組成,首先它本身是一個Binder的接口(繼承了IInterface),其次它的內部有個Stub類,這個類就是個Binder**。還記得我們怎么寫一個Binder的服務端嗎?代碼如下所示。 private final IBookManager.Stub mBinder = new IBookManager.Stub() { @Override public List<Book> getBookList() throws RemoteException { synchronized (mBookList) { return mBookList; } } @Override public void addBook(Book book) throws RemoteException { synchronized (mBookList) { if (! mBookList.contains(book)) { mBookList.add(book); } } } } **首先我們會實現一個創建了一個Stub對象并在內部實現IBookManager的接口方法,然后在Service的onBind中返回這個Stub對象。因此,從這一點來看,我們完全可以把Stub類提取出來直接作為一個獨立的Binder類來實現,這樣IBookManager中就只剩接口本身了,通過這種分離的方式可以讓它的結構變得清晰點**。 根據上面的思想,**手動實現一個Binder可以通過如下步驟來完成**: (1)聲明一個AIDL性質的接口,只需要繼承IInterface接口即可,IInterface接口中只有一個asBinder方法。這個接口的實現如下: public interface IBookManager extends IInterface { static final String DESCRIPTOR = "com.ryg.chapter_2.manualbinder.IBookManager"; static final int TRANSACTION_getBookList = IBinder.FIRST_CALL_TRANSA-CTION + 0; static final int TRANSACTION_addBook = IBinder.FIRST_CALL_TRANSACTION+ 1; public List<Book> getBookList() throws RemoteException; public void addBook(Book book) throws RemoteException; } 可以看到,**在接口中聲明了一個Binder描述符和另外兩個id,這兩個id分別表示的是getBookList和addBook方法**,這段代碼原本也是系統生成的,我們仿照系統生成的規則去手動書寫這部分代碼。如果我們有三個方法,應該怎么做呢?很顯然,我們要再聲明一個id,然后按照固定模式聲明這個新方法即可,這個比較好理解,不再多說。 (2)實現Stub類和Stub類中的Proxy代理類,這段代碼我們可以自己寫,但是寫出來后會發現和系統自動生成的代碼是一樣的,因此這個Stub類我們只需要參考系統生成的代碼即可,只是結構上需要做一下調整,調整后的代碼如下所示。 [BookManagerImpl.java](https://github.com/singwhatiwanna/android-art-res/blob/master/Chapter_2/src/com/ryg/chapter_2/manualbinder/BookManagerImpl.java) ``` package com.ryg.chapter_2.manualbinder; import java.util.List; import android.os.Binder; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; public class BookManagerImpl extends Binder implements IBookManager { /** Construct the stub at attach it to the interface. */ public BookManagerImpl() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an IBookManager interface, generating a proxy * if needed. */ public static IBookManager asInterface(IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof IBookManager))) { return ((IBookManager) iin); } return new BookManagerImpl.Proxy(obj); } @Override public IBinder asBinder() { return this; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getBookList: { data.enforceInterface(DESCRIPTOR); List<Book> result = this.getBookList(); reply.writeNoException(); reply.writeTypedList(result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); Book arg0; if ((0 != data.readInt())) { arg0 = Book.CREATOR.createFromParcel(data); } else { arg0 = null; } this.addBook(arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } @Override public List<Book> getBookList() throws RemoteException { // TODO 待實現 return null; } @Override public void addBook(Book book) throws RemoteException { // TODO 待實現 } private static class Proxy implements IBookManager { private IBinder mRemote; Proxy(IBinder remote) { mRemote = remote; } @Override public IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public List<Book> getBookList() throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); List<Book> result; try { data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(TRANSACTION_getBookList, data, reply, 0); reply.readException(); result = reply.createTypedArrayList(Book.CREATOR); } finally { reply.recycle(); data.recycle(); } return result; } @Override public void addBook(Book book) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(DESCRIPTOR); if ((book != null)) { data.writeInt(1); book.writeToParcel(data, 0); } else { data.writeInt(0); } mRemote.transact(TRANSACTION_addBook, data, reply, 0); reply.readException(); } finally { reply.recycle(); data.recycle(); } } } } ``` 通過將上述代碼和系統生成的代碼對比,可以發現簡直是一模一樣的。也許有人會問:**既然和系統生成的一模一樣,那我們為什么要手動去寫呢**?我們**在實際開發中完全可以通過AIDL文件讓系統去自動生成,手動去寫的意義在于可以讓我們更加理解Binder的工作原理,同時也提供了一種不通過AIDL文件來實現Binder的新方式**。也就是說,**AIDL文件并不是實現Binder的必需品。如果是我們手寫的Binder,那么在服務端只需要創建一個BookManagerImpl的對象并在Service的onBind方法中返回即可。最后,是否手動實現Binder沒有本質區別,二者的工作原理完全一樣,AIDL文件的本質是系統為我們提供了一種快速實現Binder的工具,僅此而已**。 接下來,我們介紹Binder的兩個很重要的方法**linkToDeath和unlinkToDeath**。我們知道,**Binder運行在服務端進程,如果服務端進程由于某種原因異常終止,這個時候我們到服務端的Binder連接斷裂(稱之為Binder死亡),會導致我們的遠程調用失敗。更為關鍵的是,如果我們不知道Binder連接已經斷裂,那么客戶端的功能就會受到影響**。 **為了解決這個問題,Binder中提供了兩個配對的方法linkToDeath和unlinkToDeath,通過linkToDeath我們可以給Binder設置一個死亡代理,當Binder死亡時,我們就會收到通知,這個時候我們就可以重新發起連接請求從而恢復連接**。那么到底如何給Binder設置死亡代理呢?也很簡單。 * 首先,**聲明一個DeathRecipient對象。DeathRecipient是一個接口,其內部只有一個方法binderDied,我們需要實現這個方法,當Binder死亡的時候,系統就會回調binderDied方法,然后我們就可以移出之前綁定的binder代理并重新綁定遠程服務**: private IBinder.DeathRecipient mDeathRecipient = new IBinder.Death- Recipient() { @Override public void binderDied() { if (mBookManager == null) return; mBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0); mBookManager = null; // TODO:這里重新綁定遠程Service } }; * 其次,**在客戶端綁定遠程服務成功后,給binder設置死亡代理**: ``` mService = IMessageBoxManager.Stub.asInterface(binder); binder.linkToDeath(mDeathRecipient, 0); ``` 其中linkToDeath的第二個參數是個標記位,我們直接設為0即可。 **經過上面兩個步驟,就給我們的Binder設置了死亡代理,當Binder死亡的時候我們就可以收到通知了。另外,通過Binder的方法isBinderAlive也可以判斷Binder是否死亡**。 到這里,IPC的基礎知識就介紹完畢了,下面開始進入正題,直面形形色色的進程間通信方式。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看