死磕AIDL

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容