AIDL基本使用(二)

来源:互联网 发布:淘宝海外集运 编辑:程序博客网 时间:2024/06/08 16:37

AIDL基本使用(二)

将观察者模式和AIDL结合起来使用,使用RemoteCallBackList管理跨进程的接口。普通接口由于使用Binder传输需要序列化和反序列化,每次客户端传递过来的都是一个新对象,无法做到解注册。而RemoteCallBackList内部使用ArrayMap,将接口和Binder对象匹配起来。

注:阅读本文章前请先阅读前一篇文章AIDL基本使用(一)

这里的观察者模式指的是客户端在服务端注册,服务端事件发生时通知客户端执行相应的事件。也就是客户端需要在服务端进行注册和解注册。本文紧接上篇文章,以图书馆(服务端)图书到来,通知客户端图书到来为例

操作步骤

1.跨进程的接口使用AIDL,所以先写一个aidl接口。

package com.example.xin.aidldemo;import com.example.xin.aidldemo.Book;interface IOnNewBookArrivedListener {    void onNewBookArrived(in Book book);}

2.在IBookManager接口中新增注册和解注册两个方法。

package com.example.xin.aidldemo;import com.example.xin.aidldemo.Book;import com.example.xin.aidldemo.IOnNewBookArrivedListener;interface IBookManager {    List<Book> getBookList();    void addBook(in Book book);    void registerListener(in IOnNewBookArrivedListener listener);    void unRegisterListener(IOnNewBookArrivedListener listener);}

3.服务端实现注册和解注册,其实就是用一个RemoteCallBackList来存放注册进来的接口,当图书到达图书馆时,逐一调用这些接口的实现。图书到达图书馆这一行为用一个线程循环执行模拟。

public class BookManagerService extends Service {    private CopyOnWriteArrayList<Book> mBookList;    private RemoteCallbackList<IOnNewBookArrivedListener> mNewBookArrivedListenerList;    private boolean isDestroy = false;    private Binder mBinder = new IBookManager.Stub() {        @Override        public List<Book> getBookList() throws RemoteException {            Log.d("ZXX","getBookList Service");            return mBookList;        }        @Override        public void addBook(Book book) throws RemoteException {            mBookList.add(book);        }        @Override        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {            //注册接口,将接口添加到RemoteCallBackList            mNewBookArrivedListenerList.register(listener);        }        @Override        public void unRegisterListener(IOnNewBookArrivedListener listener) throws RemoteException {            //解注册接口            mNewBookArrivedListenerList.unregister(listener);        }    };    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    @Override    public void onCreate() {        mBookList = new CopyOnWriteArrayList<>();        mBookList.add(new Book(1,"测试"));        mBookList.add(new Book(2,"测试2"));        mNewBookArrivedListenerList = new RemoteCallbackList<>();        new Thread(new ServiceWorker()).start();    }    //图书到达图书馆就逐一通知客户端执行    private void newBookArrived(Book book){        mNewBookArrivedListenerList.beginBroadcast();        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {            for(int i = 0; i < mNewBookArrivedListenerList.getRegisteredCallbackCount(); i++){                IOnNewBookArrivedListener listener = mNewBookArrivedListenerList.getBroadcastItem(i);                if(listener != null){                    try {                        listener.onNewBookArrived(book);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }            }        }        mNewBookArrivedListenerList.finishBroadcast();    }    @Override    public void onDestroy() {        super.onDestroy();        isDestroy = true;    }    //模拟图书到达图书馆    private class ServiceWorker implements Runnable{        @Override        public void run() {            while(!isDestroy){                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                int bookId = mBookList.size() + 1;                Log.e("ZXX","size: " + mBookList.size());                Book book = new Book(bookId, "测试"+bookId);                mBookList.add(book);                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {                    newBookArrived(book);                }            }        }    }}

4.客户端注册接口

public class MainActivity extends AppCompatActivity {    private ServiceConnection serviceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            IBookManager bookManager = IBookManager.Stub.asInterface(iBinder);            try {                List<Book> list = bookManager.getBookList();                for(Book b : list){                    Log.d("ZXX",b.getName());                }                //注册监听到服务端                bookManager.registerListener(mNewBookListener);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent(this, BookManagerService.class);        bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);    }    //注意是AIDL接口,new的时候是new 一个Stub接口    private IOnNewBookArrivedListener mNewBookListener = new IOnNewBookArrivedListener.Stub() {        @Override        public void onNewBookArrived(Book book) throws RemoteException {            Log.e("ZXX",book.getName());        }    };}

打出的Log:
08-09 23:24:20.722 23188-23188/com.example.xin.aidldemo D/ZXX: 测试
08-09 23:24:20.722 23188-23188/com.example.xin.aidldemo D/ZXX: 测试2
08-09 23:24:25.613 23188-23203/com.example.xin.aidldemo E/ZXX: 测试3
08-09 23:24:30.615 23188-23205/com.example.xin.aidldemo E/ZXX: 测试4
08-09 23:24:35.617 23188-23207/com.example.xin.aidldemo E/ZXX: 测试5
08-09 23:24:40.620 23188-23207/com.example.xin.aidldemo E/ZXX: 测试6