Binder的一些不成熟的理解

这几天看了一下Android的IPC机制, 总感觉印象不是很深刻,所以决定写写东西加深一下印象,同时也捋一下思路。
以《Android开发艺术探索》中的例子来分析,首先新建三个文件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,系统会自动在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主要起到提供供外部调用的接口以及将Service转换为IBinder的作用,IBookManager里面包含了一个叫Stub的内部类,他继承自Binder同时实现IBookManager。当客户端与服务端是同一个进程的时候,方法的调用不会走跨进程的transact过程,如果客户端和服务端不是同一个进程,方法的调用就会走跨进程的transact,transact的过程由Stub的内部类Proxy来实现:

/**
* 用于将服务端的Binder对象转换为客户端所需的接口类型的对象
* 在这里会实现客户端和服务端是否是同一个进程的判断
*/
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的构造函数中通过this.attachInterface(this, DESCRIPTOR)和descriptor绑定起来了
    //所以如果iin返回的是null,则说明服务端和客户端不是同一个进程中
    if (((iin!=null)&&(iin instanceof IBookManager))) {
        //当客户端和服务端在同一个进程内的时候,返回Stub本身
        return ((IBookManager)iin);
    }
    return new IBookManager.Stub.Proxy(obj);
}

当客户端和服务端不在同一个进程内的时候,返回的是Stub类的内部类Proxy对象,通过这个Proxy对象,可以实现跨进程的调用,调用的方法如下:

@Override 
public java.util.List<mrtang.com.ipctest.book> getBookList() throws android.os.RemoteException
{
    //_data 用于保存要调用的函数的参数
    Parcel _data = Parcel.obtain();
    //_reply  用于保存要调用的函数的返回值
    Parcel _reply = Parcel.obtain();
    //_result 用于返回客户端调用的结果
    java.util.List<Book> _result;
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        //mRemote是客户端的Binder,他是在Stub的asInterface中return new IBookManager.Stub.Proxy(obj)中的obj
        //我们通过调用他的transact方法来发送远程调用请求,与此同时当前线程挂起
        //然后服务端的onTransact方法被调用,直到调用结束,当前线程继续执行,然后从_reply中取出结果
        mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
        _reply.readException();
        _result = _reply.createTypedArrayList(Book.CREATOR);
    }
    finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

由于在transact的过程中当前线程会被挂起,所以我们不能在ui线程中进行太耗时的远程调用,接下来我们再回到Stub的onTransact方法:

/**
* 这个方法运行在服务端的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过封装后交由此方法进行处理
* 服务端通过code确定请求的目标方法是什么,然后从data中取出方法所需的参数,然后执行目标方法,将返回值放入reply中
* 此方法一般返回true,如果返回false,那么客户端的请求会失败,可以用这个特性做权限验证
*/
@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);
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容