Binder的一些不成熟的理解

這幾天看了一下Android的IPC機(jī)制, 總感覺印象不是很深刻,所以決定寫寫東西加深一下印象,同時也捋一下思路。
以《Android開發(fā)藝術(shù)探索》中的例子來分析,首先新建三個文件Book.java, Book.aidl,IBookManager.aidl,代碼如下:

//Book.java 代碼
public class Book implements Parcelable {

    int bookId;
    String bookName;

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(bookId);
        parcel.writeString(bookName);
    }

    public static final Parcelable.Creator<book> CREATOR = new Parcelable.Creator<book>(){
        @Override
        public book createFromParcel(Parcel parcel) {
            return new book(parcel);
        }

        @Override
        public book[] newArray(int i) {
            return new book[i];
        }
    };

    public Book(Parcel in){
        bookId = in.readInt();
        bookName = in.readString();
    }

    public Book(int bookId,String bookName){
        this.bookId = bookId;
        this.bookName = bookName;
    }
}

//Book.aidl 代碼
package mrtang.com.ipctest;    //包名
parcelable Book;

// IBookManager.aidl 代碼
package mrtang.com.ipctest;    //包名
import mrtang.com.ipctest.book;
interface IBookManager{
    List<book> getBookList();
    void addBook(in book book);
}

點擊make project,系統(tǒng)會自動在generated目錄下生成一個IBookManager的接口,下面就開始分析這個接口:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package mrtang.com.ipctest;
public interface IBookManager extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements mrtang.com.ipctest.IBookManager
    {
        ...
        private static class Proxy implements mrtang.com.ipctest.IBookManager
        {
           ...
        }
        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<mrtang.com.ipctest.book> getBookList() throws android.os.RemoteException;
    public void addBook(mrtang.com.ipctest.book book) throws android.os.RemoteException;
}

IBookManager接口繼承自IInterface接口,IBookManager主要起到提供供外部調(diào)用的接口以及將Service轉(zhuǎn)換為IBinder的作用,IBookManager里面包含了一個叫Stub的內(nèi)部類,他繼承自Binder同時實現(xiàn)IBookManager。當(dāng)客戶端與服務(wù)端是同一個進(jìn)程的時候,方法的調(diào)用不會走跨進(jìn)程的transact過程,如果客戶端和服務(wù)端不是同一個進(jìn)程,方法的調(diào)用就會走跨進(jìn)程的transact,transact的過程由Stub的內(nèi)部類Proxy來實現(xiàn):

/**
* 用于將服務(wù)端的Binder對象轉(zhuǎn)換為客戶端所需的接口類型的對象
* 在這里會實現(xiàn)客戶端和服務(wù)端是否是同一個進(jìn)程的判斷
*/
public static IBookManager asInterface(IBinder obj)
{
    if ((obj==null)) {
        return null;
    }
    IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    //obj.queryLocalInterface(String descriptor) 會通過傳入的descriptor返回Binder的Owner
    //Binder的Owner在Stub的構(gòu)造函數(shù)中通過this.attachInterface(this, DESCRIPTOR)和descriptor綁定起來了
    //所以如果iin返回的是null,則說明服務(wù)端和客戶端不是同一個進(jìn)程中
    if (((iin!=null)&&(iin instanceof IBookManager))) {
        //當(dāng)客戶端和服務(wù)端在同一個進(jìn)程內(nèi)的時候,返回Stub本身
        return ((IBookManager)iin);
    }
    return new IBookManager.Stub.Proxy(obj);
}

當(dāng)客戶端和服務(wù)端不在同一個進(jìn)程內(nèi)的時候,返回的是Stub類的內(nèi)部類Proxy對象,通過這個Proxy對象,可以實現(xiàn)跨進(jìn)程的調(diào)用,調(diào)用的方法如下:

@Override 
public java.util.List<mrtang.com.ipctest.book> getBookList() throws android.os.RemoteException
{
    //_data 用于保存要調(diào)用的函數(shù)的參數(shù)
    Parcel _data = Parcel.obtain();
    //_reply  用于保存要調(diào)用的函數(shù)的返回值
    Parcel _reply = Parcel.obtain();
    //_result 用于返回客戶端調(diào)用的結(jié)果
    java.util.List<Book> _result;
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        //mRemote是客戶端的Binder,他是在Stub的asInterface中return new IBookManager.Stub.Proxy(obj)中的obj
        //我們通過調(diào)用他的transact方法來發(fā)送遠(yuǎn)程調(diào)用請求,與此同時當(dāng)前線程掛起
        //然后服務(wù)端的onTransact方法被調(diào)用,直到調(diào)用結(jié)束,當(dāng)前線程繼續(xù)執(zhí)行,然后從_reply中取出結(jié)果
        mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
        _reply.readException();
        _result = _reply.createTypedArrayList(Book.CREATOR);
    }
    finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

由于在transact的過程中當(dāng)前線程會被掛起,所以我們不能在ui線程中進(jìn)行太耗時的遠(yuǎn)程調(diào)用,接下來我們再回到Stub的onTransact方法:

/**
* 這個方法運行在服務(wù)端的Binder線程池中,當(dāng)客戶端發(fā)起跨進(jìn)程請求時,遠(yuǎn)程請求會通過封裝后交由此方法進(jìn)行處理
* 服務(wù)端通過code確定請求的目標(biāo)方法是什么,然后從data中取出方法所需的參數(shù),然后執(zhí)行目標(biāo)方法,將返回值放入reply中
* 此方法一般返回true,如果返回false,那么客戶端的請求會失敗,可以用這個特性做權(quán)限驗證
*/
@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);
            java.util.List<book> _result = this.getBookList();
            reply.writeNoException();
            reply.writeTypedList(_result);
            return true;
        }
        ...
    }
    return super.onTransact(code, data, reply, flags);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容