Android笔记-Binder学习1:手写一个类似AIDL生成的文件

步骤
1、定义接口,继承IInterface,自定义两个方法

interface IBookManager extend IInterface{
    void add(Book book) throws RemoteException;

    List<Book> getList() throws RemoteException;
}

2、 定义一个静态抽象内部类:Stub
需要继承Binder 同时实现IBookManager
构造方法需要注册Binder
注册方法为attachInterface,需要传入自己和一个唯一标识DESCRIPTOR
需要定义自定义方法的唯一标识

interface IBookManager extend IInterface{
    void add(Book book) throws RemoteException;

    List<Book> getList() throws RemoteException;
     public static abstract Stub extend Binder implement IBookManager{
        //唯一标识用于注册该BInder,用包名+接口名定义
         private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";

        //getList方法唯一标识
         static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
        //add方法唯一标识
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
        public Stub(){
            //注册该binder
            this.attachInterface(this, DESCRIPTOR);

       }
     }
}

3、 Stub需要实现几个方法
asInterface:共有静态方法,供客户端获取IBookManager
onTransact:跨进程方法处理会经过该方法
asBinder:获取当前binder

interface IBookManager extend IInterface{
    void add(Book book) throws RemoteException;

    List<Book> getList() throws RemoteException;
     public static abstract Stub extend Binder implement IBookManager{
       //唯一标识用于注册该BInder,用包名+接口名定义
       private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";
        //getList方法唯一标识
         static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
        //add方法唯一标识
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
        public Stub(){
            //注册该binder
            this.attachInterface(this, DESCRIPTOR);

       }


       public static IBookManager asInterface(IBinder obj){
            if ((obj == null)) {
                return null;
            }
            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//查询当前进程
            if (((iin != null) && (iin instanceof Stub))) {
                return (Stub) iin;//当前进程返回IBookManager
            }
            return new Stub.Proxy(obj);//非当前进程返回Proxy
       }

       //该方法会处理通过代理类传递过来的方法标识code,参数载体data,返回值载体reply
       //会通过code表示判断需要执行那个方法
       //根据不同方法使用不同方式处理参数载体data,返回值载体reply
       //返回true表示执行成功,所以该方法还可以进行权限判断
       public boolean onTransact(){
           switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getList: {
                    data.enforceInterface(DESCRIPTOR);
                    List<Book> _result = this.getList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.add(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
       }

       public IBinder asBinder(){
           return this;
       }
     }


}

4、定义私有的静态代理类Prxoy,
需要实现IBookManager接口
需要实现所有自定义方法

自定义方法的实现主要步骤和原理:
- 定义参数载体_data、返回载体_reply
- 处理参数(Book),放入_data
- 调用mRemote.transact,
- 传入code 、_data、 _reply
- transact方法最终会调用Stub的onTransact,onTransact中会将处理结果放入_reply
- 最后处理_reply,生成具体对象_result(List )并返回

interface IBookManager extend IInterface{
    void add(Book book) throws RemoteException;

    List<Book> getList() throws RemoteException;
     public static abstract Stub extend Binder implement IBookManager{
       //唯一标识用于注册该BInder,用包名+接口名定义
       private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";
        //getList方法唯一标识
         static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
        //add方法唯一标识
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
        public Stub(){
            //注册该binder
            this.attachInterface(this, DESCRIPTOR);

       }


       public static void asInterface(IBinder obj){
            if ((obj == null)) {
                return null;
            }
            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//查询当前进程
            if (((iin != null) && (iin instanceof Stub))) {
                return (Stub) iin;//当前进程返回IBookManager
            }
            return new Stub.Proxy(obj);//非当前进程返回Proxy
       }

       //该方法会处理通过代理类传递过来的方法标识code,参数载体data,返回值载体reply
       //会通过code表示判断需要执行那个方法
       //根据不同方法使用不同方式处理参数载体data,返回值载体reply
       //返回true表示执行成功,所以该方法还可以进行权限判断
       public boolean onTransact(){
           switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getList: {
                    data.enforceInterface(DESCRIPTOR);
                    List<Book> _result = this.getList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.add(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
       }

       public IBinder asBinder(){
           return this;
       }
     }

     private static class Proxy implements IBookManager {
            private IBinder mRemote;

            public String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            public Proxy(IBinder obj) {
                this.mRemote = obj;
            }

            //自定义方法的实现主要步骤和原理:
            //定义参数载体_data,返回载体_reply
            //处理参数(Book),放入_data
            //调用mRemote.transact,
            //传入code _data _reply
            //该方法会调用Stub的onTransact,onTransact中会降返回结果放入_reply
            //最后处理_reply,生成具体对象_result(List<Book> )并返回
            @Override
            public void add(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_add, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public List<Book> getList() throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                List<Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(TRANSACTION_getList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public IBinder asBinder() {
                return mRemote;
            }
        }
}

至此一个完整的AIDL就手写完成。
实现思想:
当前进程:不需要处理数据的跨进程传递,所以可以直接使用接口
非当前进程:需要处理数据的跨进程传递,所以要使用代理接口,代理接口的作用是:处理数据的跨进程。而且看起来客户端得调用方式和同进程是一样的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值