Binder学习记录,持续更新

  Binder 是Android 中的一个类,实现了IBinder接口。那么具体Binder 是什么呢?我个人经过多个博客的翻阅,Binder是Android 底层的一个驱动。从IPC 上来说,Binder是跨进程通讯的方式,内部使用了代理模式来实现数据的通讯。(由于本人还没有从FrameWork角度来研究Binder就不闲谈这一方面了),我们大部分见到Binder 是在Service 中的BindService 启动模式中绑定的Binder,一般常用的也是这种方式。普通的Service 中的Binder 不涉及到Binder 的跨进程通信。在Android 中运用跨进程通信的规范是AIDL ,这是一种模式,我们也可以完全不用AIDL 自己去写 实现IInterface 的Binder类,不过比较麻烦,适合喜欢深入研究的同学们,其内部和AIDL 生成的一样。

  好了我们已经初步的介绍了Binder 是一个怎么样子的概念。接下来是代码部分,使用Android Studio 生成的AIDL文件中的java 接口。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\Android\\AIDL\\app\\src\\main\\aidl\\com\\example\\administrator\\aidl\\BookController.aidl
 */
package com.example.administrator.aidl;

public interface BookController extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.example.administrator.aidl.BookController {
        private static final java.lang.String DESCRIPTOR = "com.example.administrator.aidl.BookController";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.example.administrator.aidl.BookController interface,
         * generating a proxy if needed.
         */
        public static com.example.administrator.aidl.BookController asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.administrator.aidl.BookController))) {
                return ((com.example.administrator.aidl.BookController) iin);
            }
            return new com.example.administrator.aidl.BookController.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 {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_getBookList: {
                    data.enforceInterface(descriptor);
                    java.util.List<com.example.administrator.aidl.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBookInOut: {
                    data.enforceInterface(descriptor);
                    com.example.administrator.aidl.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.administrator.aidl.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBookInOut(_arg0);
                    reply.writeNoException();
                    if ((_arg0 != null)) {
                        reply.writeInt(1);
                        _arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        private static class Proxy implements com.example.administrator.aidl.BookController {
            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;
            }

            /**
             * Demonstrates some basic types that you can use as parameters
             * and return values in AIDL.
             */
            @Override
            public java.util.List<com.example.administrator.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.example.administrator.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.example.administrator.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBookInOut(com.example.administrator.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_addBookInOut, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        book.readFromParcel(_reply);
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addBookInOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    public java.util.List<com.example.administrator.aidl.Book> getBookList() throws android.os.RemoteException;

    public void addBookInOut(com.example.administrator.aidl.Book book) throws android.os.RemoteException;
}

从这个类的最后两行代码我们可以得知,我创建的AIDL 文件功能是getBookList 和addBookInout两个函数(方法)。那么在Service 调用的时候我们会 new BookController.Stub() 生成实例并且实现回调方法getBookList 和addBookInout!为什么要new new BookController.Stub() 我们可以点开java 文件去查看public static abstract class Stub extends android.os.Binder implements com.example.administrator.aidl.BookController  Stub 作为BookController 的静态内部类 继承了Binder 实现了BookController ,那么Stub就是BookController 的实现类,而且Stub 中还有一个 Proxy 的静态内部类,这个类是Stub 的代理类,实现具体的业务使用到的。(我们可以在Android 源码中发现大量的使用了Proxy 代理模式,大家在观察源码的同时一定要多学习代码结构。)这个代理类中实现了我们定义的那两个抽象方法! getBookList和addBookInOut 。这个代理类Proxy 就是跨进程的实现类。而Stub 是内部的是本地的实现类。在我们new BookController.Stub的时候 Stub 的构造方法调用binder的attchInterface方法,将自己传入Binder 的全局中保存,并且带进去一个常量“DESCRIPTOR ”这个常量是Binder 的唯一标识符 也就是BookController.Stub 唯一的标识符。具体作用是用来表示判断是客户端和服务端是否在同一个进程内 ,是就返回 自己本身对象,不是就创建代理对象进行跨进程通信 。返回本地的就调用Service 中的实现就好了,没有什么逻辑可言。

  如果是跨进程,那么就会创建一个Proxy 并且传入Service 中的Stub 对象到Proxy 中保存起来。调用Stub 对象(mRemote )的transact 核心方法进行处理。这个方法在Binder 中实现。transact 方法需要传入四个参数第一个参数是方法标识,第二个参数是 需要取出的值,第三个是接收服务端返回的值,第四个默认写0,目前点进去发现没有用到(_data.writeInt 这个方法虽然没有看到源码,点进去之后发现是key,value 形式,个人观点应根据传递的0 和1 来判断值,如果1就是有值,0就是没值)。transact 内部会调用onTransact  这个方法内部会进行一些取值和存储操作,并且调用Service 中的Stub 重写的方法进行值的操作。然后返回一个布尔boolean状态,我们可以根据这个状态判断是否 通信完成。

  如何判断Binder  客户端是否和服务端是连接状态呢?Binder 中有一个方法linkToDeatch   为Binder 设置一个死亡代理,Binder 如果中断连接,就会触发这个代理,我们可以在代理中进行重新连接或者其他的动作,具体是怎么使用的 只需要linToDeatch(new IBinder.DeatchRecpient{ …………})

这就是binder 的核心部分。下片文章介绍Messenger。请

  大家帮小弟发现不足之处进行补充,第一次写这么深刻的博客,激动的半夜2点还没睡。

 

 
 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值