美文网首页
死磕AIDL

死磕AIDL

作者: 程序员要多喝水 | 来源:发表于2019-11-30 18:17 被阅读0次

    AIDL:一种IPC跨进程调用远程服务方式,如果是同一个进程之内,没必要使用AIDL;

    如下例子一步步揭开AIDL谜题

    首先第一步创建一个model实体类,并且需要Parcelable:

    
    public class Book implements Parcelable {
        private String name;
    
        public Book(Parcel in) {
            this.name = in.readString();
        }
    
        public Book(String name) {
            this.name = name;
        }
    
        public static final Creator<Book> CREATOR = new Creator<Book>() {
            @Override
            public Book createFromParcel(Parcel in) {
                return new Book(in);
            }
    
            @Override
            public Book[] newArray(int size) {
                return new Book[size];
            }
        };
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.name);
        }
    }
    
    

    然后在实体同包名下创建一个Book.aidl

    // Book.aidl
    package com.mi.learn.aidllib;
    
    parcelable Book;
    

    之后在创建一个远程调用的IBookManaer.aidl文件:

    // IBookManager.aidl
    package com.mi.learn.aidllib;
    // Declare any non-default types here with import statements
    import com.mi.learn.aidllib.Book;
    
    interface IBookManager {
    
         List<Book> getListBook();
    
         void addBook(in Book book);
    
    }
    

    编译后会生成IBookManager.java文件

    package com.mi.learn.aidllib;
    
    public interface IBookManager extends android.os.IInterface {
        /**
         * Local-side IPC implementation stub class.
         */
        public static abstract class Stub extends android.os.Binder implements com.mi.learn.aidllib.IBookManager {
            private static final java.lang.String DESCRIPTOR = "com.mi.learn.aidllib.IBookManager";
    
            /**
             * Construct the stub at attach it to the interface.
             */
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
    
            /**
             * Cast an IBinder object into an com.mi.learn.aidllib.IBookManager interface,
             * generating a proxy if needed.
             */
            public static com.mi.learn.aidllib.IBookManager asInterface(android.os.IBinder obj) {
                if ((obj == null)) {
                    return null;
                }
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.mi.learn.aidllib.IBookManager))) {
                    return ((com.mi.learn.aidllib.IBookManager) iin);
                }
                return new com.mi.learn.aidllib.IBookManager.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_getListBook: {
                        data.enforceInterface(descriptor);
                        java.util.List<com.mi.learn.aidllib.Book> _result = this.getListBook();
                        reply.writeNoException();
                        reply.writeTypedList(_result);
                        return true;
                    }
                    case TRANSACTION_addBook: {
                        data.enforceInterface(descriptor);
                        com.mi.learn.aidllib.Book _arg0;
                        if ((0 != data.readInt())) {
                            _arg0 = com.mi.learn.aidllib.Book.CREATOR.createFromParcel(data);
                        } else {
                            _arg0 = null;
                        }
                        this.addBook(_arg0);
                        reply.writeNoException();
                        return true;
                    }
                    default: {
                        return super.onTransact(code, data, reply, flags);
                    }
                }
            }
    
            private static class Proxy implements com.mi.learn.aidllib.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;
                }
    
                @Override
                public java.util.List<com.mi.learn.aidllib.Book> getListBook() throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.util.List<com.mi.learn.aidllib.Book> _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        mRemote.transact(Stub.TRANSACTION_getListBook, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.createTypedArrayList(com.mi.learn.aidllib.Book.CREATOR);
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }
    
                @Override
                public void addBook(com.mi.learn.aidllib.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();
                    }
                }
            }
    
            static final int TRANSACTION_getListBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
            static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    
        public java.util.List<com.mi.learn.aidllib.Book> getListBook() throws android.os.RemoteException;
    
        public void addBook(com.mi.learn.aidllib.Book book) throws android.os.RemoteException;
    
    

    可以看出来,这个IBookManager.java文件几个重要点:
    DESCRIPTOR:唯一标识;
    IBookManager#asInterface:判断同一进程,返回stub,跨进程,返回Stub.Proxy;
    IBookManager#asBinder:返回IBookManager自身;
    IBookManager#onTransact:处理各种方法;

    IBookManager#Proxy#asBinder:返回是一个mRemote,即IBookManager#asInterface方法传过去的Ibinder;

    IBookManager#Proxy#getListBook:代理类的提供方法
    IBookManager#Proxy#addBook:代理类的提供方法

    之后创建一个服务端BookManagerService:

    public class BookManagerService extends Service
    {
        private static final String TAG = "AIDL-Server";
    
        private List<Book> list = new ArrayList<>();
    
    
        private Binder mBinder = new IBookManager.Stub() {
            @Override
            public List<Book> getListBook() throws RemoteException {
                Log.d(TAG,"getListBook :" + Thread.currentThread().getName());
                return list;
            }
    
            @Override
            public void addBook(Book book) throws RemoteException {
                Log.d(TAG,"addBook :" + Thread.currentThread().getName());
                list.add(book);
            }
    
        };
    
    
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG,"onBind");
            return mBinder;
        }
    }
    //AndroidManifest.xml指定下process
    <service android:name=".BookManagerService"
                android:process=":remote">
                <intent-filter>
                    <action android:name="com.mi.learn.server.bookmanagerservice"/>
                </intent-filter>
            </service>
    
    

    客户端调用代码:

    private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG,"onServiceConnected :" + Thread.currentThread().getName());
                            bookManager = IBookManager.Stub.asInterface(service);
    
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.d(TAG,"onServiceDisconnected :" + Thread.currentThread().getName());
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            Intent intent = new Intent("com.mi.learn.server.bookmanagerservice").setPackage("com.mi.learn.client");
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
        }
        
         @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.addBook:
                       try {
                            bookManager.addBook(new Book("this is a book"));
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    break;
                case R.id.getBook:
                    try {
                            tv.setText(bookManager.getListBook().toString());
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    break;
            }
        }
    
    

    至此,最简单不稳定的AIDL实现了;

    说不稳定有一个地方:
    1.服务端可能被多个客户端同时访问,服务端需要线程同步;
    2.客户端没有处理服务端进程突然死亡情况;
    3.客户端很多服务处理在主线程,会造成ANR;

    下面来说如何一步步优化:
    1.服务端可能被多个客户端同时访问,服务端需要线程同步;
    ArrayList集合时线程不同步的,那么如何做到线程同步呢,在不加锁情况下换成CopyOnWriteArrayList

    2.客户端没有处理服务端进程突然死亡情况;
    可以使用DeathRecipient机制;
    Binder服务端挂掉时候会发一个通知,然后调用DeathRecipient#binderDied,可以在此处死亡时候重新bindService;

    3.客户端很多服务处理在主线程,会造成ANR;
    点击事件调用bookManager.addBook和bookManager.getListBook都是在主线程进程的,
    在点击时候,服务端如果耗时操作,那么这里会卡住,严重会出现ANR;
    ServiceConnection回调的onServiceConnected和onServiceDisconnected也是运行在主线程的;而服务端的BookManagerService#IBookManager.Stub的getListBook和addBook在IPC时候处于binder线程池中运行;因此可以创建线程处理,用handler更新即可;

    看下改进后的代码

    
    //使用WeakReference防止内存泄露
     private MyHandler handler = new MyHandler(this);
    
        private class MyHandler extends Handler{
            private WeakReference<Activity> weakReference;
    
            private MyHandler(Activity activity){
                weakReference = new WeakReference<>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                Activity activity = weakReference.get();
                if (activity == null){
                    return;
                }
                switch (msg.what){
                    switch (msg.what){
                    case ADD_BOOK_MESSAGE:
                        Toast.makeText(activity,"add book success",Toast.LENGTH_SHORT).show();
                        break;
                    case GET_BOOK_MESSAGE:
                    case NOTIFY_BOOK_MESSAGE:
                        List<Book>list= (List<Book>) msg.obj;
                        tv.setText(list.toString());
                        break;
                    default:
                        break;
                }
            }
        }
    
        //死亡回调,重新bindService
        private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
            @Override
            public void binderDied() {
               if (bookManager!=null){
                   bookManager.asBinder().unlinkToDeath(deathRecipient,0);
                   bookManager = null;
                   bindService();
               }
            }
        };
    
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG,"onServiceConnected :" + Thread.currentThread().getName());
                Log.d(TAG,"onServiceConnected IBinder :" + service.toString());
                //拿到Stub.Proxy代理类
                bookManager = IBookManager.Stub.asInterface(service);
                try {
                    bookManager.asBinder().linkToDeath(deathRecipient,0);
                    Log.i(TAG,"callback address"+callBack.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.d(TAG,"onServiceDisconnected :" + Thread.currentThread().getName());
    
            }
        };
    
    
    //点击事件运行在子线程,然后通过handler到UI线程
       @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.addBook:
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (bookManager!=null){
                                    bookManager.addBook(new Book("this is a book"));
                                }
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            }
                            handler.sendMessage(Message.obtain(handler,ADD_BOOK_MESSAGE));
                        }
                    }).start();
                    break;
                case R.id.getBook:
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (bookManager!=null){
                                    handler.sendMessage(Message.obtain(handler,GET_BOOK_MESSAGE,bookManager.getListBook()));
                                }
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                    break;
            }
        }
    
    public class BookManagerService extends Service
    {
        private static final String TAG = "AIDL-Server";
    
        private CopyOnWriteArrayList<Book> list = new CopyOnWriteArrayList<>();
     
    
    
        private Binder mBinder = new IBookManager.Stub() {
            @Override
            public List<Book> getListBook() throws RemoteException {
            //延迟5S,模拟耗时
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(TAG,"getListBook :" + Thread.currentThread().getName());
                return list;
            }
    
            @Override
            public void addBook(Book book) throws RemoteException {
                //延迟5S,模拟耗时
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(TAG,"addBook :" + Thread.currentThread().getName());
                list.add(book);
            }
    

    有时候服务端会有数据更新,那如何通知到客户端实现一种观察者模式呢?
    这里就需要在客户端注册一个callback类型的binder到服务端,此时服务端持有callback类型binder的代理类也就是BinderProxy,客户端相当于这个CallBack Binder的服务端,服务端相当于这个CallBack Binder的客户端;
    如下步骤,创建一个IBookCallBack.aidl

    interface IBookCallBack {
        void notifyClient(inout List<Book> list);
    }
    

    修改IBookManager.aidl:

    interface IBookManager {
         List<Book> getListBook();
         void addBook(in Book book);
         void register(in IBookCallBack callback);
         void unregister(in IBookCallBack callback);
    }
    

    客户端此时相当于服务端,而服务端相当于客户端,客户端代码:

    //需要注意这里可能回调过来在binder线程池中
    private Binder callBack = new IBookCallBack.Stub() {
            @Override
            public void notifyClient(final List<Book> list) throws RemoteException {
                Log.d(TAG,"notifyClient :" + Thread.currentThread().getName());
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        handler.sendMessage(Message.obtain(handler,NOTIFY_BOOK_MESSAGE,list));
                    }
                }).start();
            }
        };
        
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG,"onServiceConnected :" + Thread.currentThread().getName());
                Log.d(TAG,"onServiceConnected IBinder :" + service.toString());
    
                bookManager = IBookManager.Stub.asInterface(service);
                try {
                    bookManager.asBinder().linkToDeath(deathRecipient,0);
                    Log.i(TAG,"callback address"+callBack.toString());
                    //注册
                    bookManager.register((IBookCallBack) callBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            
            
            protected void onDestroy() {
            super.onDestroy();
            if (bookManager!=null && bookManager.asBinder().isBinderAlive()){
                try {
                //解注册
                    bookManager.unregister((IBookCallBack) callBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                bookManager.asBinder().unlinkToDeath(deathRecipient,0);
                bookManager = null;
            }
            unbindService(serviceConnection);
    
            handler.removeCallbacksAndMessages(null);
        }
    

    服务端BookManagerService代码:

    public class BookManagerService extends Service
    {
        private static final String TAG = "AIDL-Server";
    
        private CopyOnWriteArrayList<Book> list = new CopyOnWriteArrayList<>();
        private final RemoteCallbackList<IBookCallBack> remoteCallBackList = new RemoteCallbackList<IBookCallBack>();
    
    
        private Binder mBinder = new IBookManager.Stub() {
            @Override
            public List<Book> getListBook() throws RemoteException {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(TAG,"getListBook :" + Thread.currentThread().getName());
                return list;
            }
    
            @Override
            public void addBook(Book book) throws RemoteException {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(TAG,"addBook :" + Thread.currentThread().getName());
                list.add(book);
                synchronized (BookManagerService.this){
                    int size = remoteCallBackList.beginBroadcast();
                    for (int i = 0; i< size; i++){
                        IBookCallBack callBack = remoteCallBackList.getBroadcastItem(i);
                        try {
                            callBack.notifyClient(list);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                    remoteCallBackList.finishBroadcast();
                }
            }
    
            @Override
            public void register(IBookCallBack callback) throws RemoteException {
                Log.i(TAG,"callback address"+callback.toString());
                synchronized (BookManagerService.this){
                    remoteCallBackList.register(callback);
                    int size = remoteCallBackList.beginBroadcast();
                    Log.i(TAG,"after register size:"+size);
                    remoteCallBackList.finishBroadcast();
                }
            }
    
            @Override
            public void unregister(IBookCallBack callback) throws RemoteException {
                synchronized (BookManagerService.this){
                    remoteCallBackList.unregister(callback);
                    int size = remoteCallBackList.beginBroadcast();
                    Log.i(TAG,"after unregister size:"+size);
                    remoteCallBackList.finishBroadcast();
                }
            }
        };
    
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG,"onBind");
            isServiceOk.set(true);
            new addBookThread().start();
            return mBinder;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d(TAG,"onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.d(TAG,"onUnbind");
            isServiceOk.set(false);
            return super.onUnbind(intent);
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG,"onCreate");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestroy");
        }
    
        private AtomicBoolean isServiceOk = new AtomicBoolean(false);
    
        private class addBookThread extends Thread{
            @Override
            public void run() {
                while (isServiceOk.get()){
                    list.add(new Book("this is increase book"));
                    synchronized (BookManagerService.this){
                        int size = remoteCallBackList.beginBroadcast();
                        for (int i = 0; i< size; i++){
                            IBookCallBack callBack = remoteCallBackList.getBroadcastItem(i);
                            try {
                                Log.d(TAG,"server notifyClient:"+Thread.currentThread().getName());
                                Log.d(TAG,"server notifyClient:"+callBack.toString());
                                callBack.notifyClient(list);
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            }
                        }
                        remoteCallBackList.finishBroadcast();
                    }
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    

    在BookManagerService#onCreate创建一个线程,每隔10S添加一本书,然后通过notifyClient回调到客户端,此过程就是服务端持有的是IBookCallBack.Stub.Proxy,而客户端的IBookCallBack.Stub是真正的服务处理;
    这里使用RemoteCallbackList<IBookCallBack> remoteCallBackList ;这个类里面实现了死亡回调DeathRecipient过程,因此如果客户端挂了,那么这里也就不用回调了;需要注意remoteCallBackList需要线程同步;

    如果服务端BookManagerService经过10S增加一本书到客户端notifyClient显示,这里回调是在binder线程池中,而如上调用客户端通过bookManager.addBook(book),在服务端addBook处理在回调到客户端的notifyClient时候,是在UI线程中的,这地方需要注意下,因此回调不一定就在binder线程池中;

    Binder线程池总结

    总结如下图所示
    (1)场景1,客户端主线程点击Click事件,调用服务端方法addBook,
    客户端在主线程,服务端此时应该是在 Binder线程池中;

    graph TB
             subgraph client
             Client-MainThread
             end
             
             subgraph Server
             Server-Stub1
             end
             Client-MainThread-->Server-Stub1
    

    (2)服务端Server通过new Thread方式创建线程,在线程方法中调用客户端Client Stub1服务,此时服务端在new Thread方法上,客户端在Binder线程池中;上面服务端开一个线程,每过10S添加一本Book,然后不断通知客户端有数据更新,此操作大致模型如下:

    graph TB
             subgraph client
             Client-MainThread
             Client-Stub1
             end
             
             subgraph Server
             Server-newthread
             end
             Server-newthread-->Client-Stub1
    

    (3)如果客户端调用服务端AddBook,然后服务端Add完毕后,在调用客户端的方法Stub1,之后客户端在调用服务端Stub2,于是模型如下:

    graph TB
             subgraph client
             Client-MainThread
             Client-Stub1
             end
             
             subgraph Server
             Server-Stub1
             Server-Stub2
             end
             Client-MainThread-->Server-Stub1
             Server-Stub1 --> Client-Stub1
             Client-Stub1 --> Server-Stub2
    
    

    客户端主线程请求服务的Stub1服务时候,客户端运行主线并且阻塞,服务端运行在Binder线程池中,假设现在叫binder_2333线程中;
    如果server-stub1需要调用client-stub1服务时候,此时client-stub1运行在主线程中;
    如果Client-Stub1还需要调用Server-Stub2服务,此时Server-Stub2会运行在binder_2333这个线程池中;
    这其中原因是因为binder线程池中有一个线程复用的原则,具体这里不分析;

    OneWay和非OneWay

    还有需要注意AIDL中oneway和非oneway方式区别;
    非oneway如上分析,客户端主线程的bookmanager.add调用时阻塞的,如果服务端的binder.add没处理完,客户端一直阻塞,如果没处理好会ANR,因此客户端在调用服务端时候时waitForResponse;
    oneway就是客户端时候不会阻塞;

    In/Out/InOut

    还有AIDL的输入参数in,out,inout区别,如下

         void addBook(in Book book);
    

    in时客户端将数据拷贝到服务端,如果服务端修传入的Book值,客户端传入的Book时不会发生改变的
    out时,客户端没有将数据拷贝到服务端,此时时new Book的,但是处理完后,服务端会将数据拷贝到客户端,因此调用完后,客户端时一个 new Book,当然我们服务端修改Book属性,客户端就会拿到服务端修改的值;
    inout就是客户端会将Book拷贝到服务端,服务端修改后也会将数据传给客户端;

    Binder连接池

    如果服务端Binder很多,可以考虑是用Binder连接池,首先建立如下AIDL:

    // IBinderPool.aidl
    package com.mi.learn.binder;
    
    // Declare any non-default types here with import statements
    
    interface IBinderPool {
        IBinder queryBinder(in int code);
    }
    

    通过queryBinder方法参数code不同服务端返回不同的binder,如下服务端代码:

    private IBinder binderPool = new IBinderPool.Stub() {
            @Override
            public IBinder queryBinder(int code) throws RemoteException {
                switch (code){
                    case BOOK_BINDER:
                        return bookBinder;
                    case PERSON_BINDER:
                        return personBinder;
                }
                return null;
            }
        };
    

    进一步,可以封装一个专门针对这种服务的工具类如下:

    package com.mi.learn.binder;
    
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class BinderPoolUtils {
        private IBinderPool mBinderPool;
        private Context mContext;
        private Intent mIntent;
        private BinderPoolLifeCycle mLifeCycle;
    
        public BinderPoolUtils(Context mContext, Intent mIntent, BinderPoolLifeCycle mLifeCycle) {
            this.mContext = mContext;
            this.mIntent = mIntent;
            this.mLifeCycle = mLifeCycle;
        }
    
        public interface BinderPoolLifeCycle{
            void onServiceConnected(IBinderPool binderPool);
            void onServiceDisconnected(ComponentName name);
            void binderDied();
    
        }
    
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mBinderPool = IBinderPool.Stub.asInterface(service);
                try {
                    mBinderPool.asBinder().linkToDeath(deathRecipient,0);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                mLifeCycle.onServiceConnected(mBinderPool);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mLifeCycle.onServiceDisconnected(name);
            }
        };
    
        private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
            @Override
            public void binderDied() {
                if (mBinderPool != null){
                    mBinderPool.asBinder().unlinkToDeath(deathRecipient,0);
                    mBinderPool = null;
                    mLifeCycle.binderDied();
                    bindPoolService();
                }
    
            }
        };
    
        public void bindPoolService(){
            mContext.bindService(mIntent, connection,Context.BIND_AUTO_CREATE);
        }
    
        public void unBindPoolService(){
            if (mBinderPool != null && mBinderPool.asBinder().isBinderAlive()){
                mBinderPool.asBinder().unlinkToDeath(deathRecipient,0);
                mBinderPool = null;
            }
            mContext.unbindService(connection);
        }
    }
    

    通过接口方式回调Binder的几个关键的方法,客户端主要调用几个关键方法即可:

    private void init() {
            mBinderPoolUtils = new BinderPoolUtils(this,
                    new Intent(this,BookManagerService.class),
                    this);
            mBinderPoolUtils.bindPoolService();
        }
    
    
     @Override
     public void onServiceConnected(IBinderPool binderPool) {
            try {
                mBookBinder = IBookBinder.Stub.asInterface(binderPool.queryBinder(BOOK_BINDER));
                mBookBinder.register(callBack);
                mPersonBinder = IPersonBinder.Stub.asInterface(binderPool.queryBinder(PERSON_BINDER));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
    @Override
    public void onServiceDisconnected(ComponentName name) {}
    
    @Override
    public void binderDied() {
            try {
                mBookBinder.unregister(callBack);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mBookBinder = null;
            mPersonBinder = null;
        }
        
     @Override
    protected void onDestroy() {
            super.onDestroy();
            mBinderPoolUtils.unBindPoolService();
        }
    

    到此AIDL细节东西基本介绍完毕,模拟实践可以更快更好的理解这些原理;
    贴上个人写的AIDL实例:https://github.com/1036711153/Learning

    相关文章

      网友评论

          本文标题:死磕AIDL

          本文链接:https://www.haomeiwen.com/subject/jaaowctx.html