进程间通信学习系列(二)——简单了解Binder机制

 

进程间通信学习系列(一)——IPC简介


Binder机制太复杂了,本文只是简单的对Binder进行了解。

在Android中Binder是一个类,实现了IBinder接口,在Binder机制中还有两个重要角色Binder驱动(在内核中)和ServiceManager,这两部分Android平台已经实现,我们不必关心,当然有兴趣的童鞋可以研究下。本文主要学习了解应用层的Client和Service相关的Binder知识。

Messenge,ContentProvider等底层实现都是AIDL,所以以AIDL的简单实现来学习Binder机制。

需求:图书管理系统中,1.需要查询图书列表;2.添加新书到图书库中。

先看一下目录结构:

进程间通信学习系列(二)——简单了解Binder机制_第1张图片












首先新建一个Book类,并实现Parcelable序列化接口(Android Studio一键生成序列化代码插件),如下:

public class Book implements Parcelable {
    private double price;
    private long bookId;
    private String bookName;

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeDouble(this.price);
        dest.writeLong(this.bookId);
        dest.writeString(this.bookName);
    }

    public Book() {
    }

    protected Book(Parcel in) {
        this.price = in.readDouble();
        this.bookId = in.readLong();
        this.bookName = in.readString();
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
}
新建IBookManager.aidl文件,生命两个接口:

package anyan.com.ipcdemo.aboutaidl;
//注意导入Book类(手动导入)
import anyan.com.ipcdemo.aboutaidl.Book;

interface IBookManager {
    List getBookList();//查询图书列表
    void addBook(in Book book);//添加新图书
}

因为在IBookManager.aidl文件中使用了非基本数据类型,所以Book类不仅要实现序列化接口,还要新建一个Book.aidl文件(至于为什么,我也不知道),注意这个Book.aidl文件的全路径包名要与Book.java的全路径包名一致,否则编译会报错。内容如下:

package anyan.com.ipcdemo.aboutaidl;

parcelable Book;
Rebuild project成功后再app/build/generated/source/aidl/debug/包名 目录下回生成一个IBookManager.java文件,这是AS帮我们自动生成的,这里使用了代理模式(可简单了解一下, Java设计模式-代理模式实现及原理)主要分析这里的代码:包含两个接口getBookList()和addBook(),可以看到这两个接口就是我们在IBookManager.aidl文件中所声明的。一个内部类Stub,继承Binder实现IBookManager接口。Stub类里面还有一个内部类Proxy也实现了IBookManager接口,这个就是Stub类(也就是Binder)的代理类。

public interface IBookManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements anyan.com.ipcdemo.aboutaidl.IBookManager {
        //Binder的唯一标识,一般用类名表示
        private static final java.lang.String DESCRIPTOR = "anyan.com.ipcdemo.aboutaidl.IBookManager";

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

        /**
         * Cast an IBinder object into an anyan.com.ipcdemo.aboutaidl.IBookManager interface,
         * generating a proxy if needed.
         * 将IBinder对象转换成IBookManager接口并返回
         * 这种转换区分进程,如果是在同一进程,直接返回服务端的Stub对象;
         * 如果不在同一进程,则返回代理对象Stub.Proxy;
         */
        public static anyan.com.ipcdemo.aboutaidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof anyan.com.ipcdemo.aboutaidl.IBookManager))) {
                return ((anyan.com.ipcdemo.aboutaidl.IBookManager) iin);
            }
            return new anyan.com.ipcdemo.aboutaidl.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        /**
         * 该方法在服务端的Binder线程池中执行,注意采用同步方法
         * @param code 确定客户端请求的目标方法是哪个
         * @param data 目标方法所需参数数据
         * @param reply 目标方法返回数据
         * @param flags
         * @return
         * @throws android.os.RemoteException
         */
        @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 _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    anyan.com.ipcdemo.aboutaidl.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = anyan.com.ipcdemo.aboutaidl.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        //代理对象
        private static class Proxy implements anyan.com.ipcdemo.aboutaidl.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;
            }

            /**
             * 该方法在客户端执行,
             * @return
             * @throws android.os.RemoteException
             */
            @Override
            public java.util.List getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //调用远程请求,当前线程挂起,服务端OnTransact()方法会被调用,
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    //当前线程继续执行,取出结果
                    _reply.readException();
                    _result = _reply.createTypedArrayList(anyan.com.ipcdemo.aboutaidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(anyan.com.ipcdemo.aboutaidl.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();
                }
            }
        }
        
        //方法的id
        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 getBookList() throws android.os.RemoteException;

    public void addBook(anyan.com.ipcdemo.aboutaidl.Book book) throws android.os.RemoteException;
}
如下图所示:

进程间通信学习系列(二)——简单了解Binder机制_第2张图片









接着看具体怎么使用,创建一个BookManagerService类:

public class BookService extends Service {
    public BookService() {
    }

    //支持并发读写
    private CopyOnWriteArrayList bookList = new CopyOnWriteArrayList<>();

    private IBookManager.Stub binder = new IBookManager.Stub() {
        @Override
        public List getBookList() throws RemoteException {
            return bookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            bookList.add(book);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
}

在Activity中BindService:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private IBookManager iBookManager;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //用到了上面提到了转换方法asInterface,将IBinder转换为接口,
            //同一进程直接返回Stub对象,不同进程返回Proxy代理类
            iBookManager = IBookManager.Stub.asInterface(service);
            try {
                service.linkToDeath(deathRecipient, 0);
                //拿到对象后就可以直接调用方法了
                List bookList = iBookManager.getBookList();
                Log.e(TAG, "onServiceConnected: " + bookList);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    //死亡代理,binder死亡时会收到通知,回调binderDied方法
    private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            if (iBookManager == null)
                return;
            iBookManager.asBinder().unlinkToDeath(deathRecipient, 0);
            iBookManager = null;
            //重新绑定service
            Intent intent = new Intent(MainActivity.this, BookService.class);
            bindService(intent, conn, BIND_AUTO_CREATE);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void onClick(View view) {
        Intent intent = new Intent(this, BookService.class);
        bindService(intent, conn, BIND_AUTO_CREATE);
    }
}
至此,简单的Binder机制分析完了,看着可能有点懵,很正常,我是看了好几篇才只是简单的理解了。Fighting !!!



你可能感兴趣的:(Android)