IPC机制---04 Android中的IPC通讯方式(C)

来源:互联网 发布:重生之美国仓储淘宝王 编辑:程序博客网 时间:2024/04/30 15:25
  • 上一篇中,在服务端的BookService中使用的是ArrayList,这是一个线程不安全的集合,因为AIDL的方法是在Binder的线程池中执行的,因此当多个客户端同时连接的时候,会存在多个线程同时访问的情况,所以我们要在AIDL方法中处理线程同步,下面使用一个新的集合类来代替它--CopyOnWriteArrayList
  • CopyOnWriteArrayList
    • 支持并发读/写
    • 能自动进行线程同步
    • 之前提到,AIDL中支持的List只有ArrayList,而我们用其对ArrayList进行替换,但CopyOnWriteArrayList不是继承自ArrayList。
    • 虽然服务端返回的是一个CopyOnWriteArrayList,但是在Binder中会按照List的规范去访问数据并最终形成一个新的ArrayList传递给客户端,因此使用CopyOnWriteArrayList是完成可以的,同样的还有ConcurrentHashMap。
  • 下面对该demo进行扩展,使用观察者模式,这样一种需求,用户不需要每次都去进行新书的获取,而是有新书的时候,主动去提醒进行订阅的用户,同样,用户也可以取消订阅。
    • 首先,提供一个AIDL接口,每个用户都需要实现这个接口并向图书馆申请新书的提醒功能,之所以选择AIDL接口是因为AIDL中无法使用普通接口。
  • 服务端
    • 定义IOnNewBookArrivedListener.aidl,提供onNewBookArrived方法,如下:
    // IONewBookArrivedListener.aidlpackage com.happy.ipc.server;import com.happy.ipc.server.domain.Book;// Declare any non-default types here with import statementsinterface IONewBookArrivedListener {   void onNewBookArrived(in Book book);}
    • 在IBookManager.aidl文件中添加注册和取消注册方法,如下:
    // IBookManager.aidlpackage com.happy.ipc.server;import com.happy.ipc.server.domain.Book;import com.happy.ipc.server.IONewBookArrivedListener;// Declare any non-default types here with import statementsinterface IBookManager {   int getBookCount();   List<Book> addBook(in Book book);   void registerNewBookArrivedListener(IONewBookArrivedListener listener);   void unRegisterNewBookArrivedListener(IONewBookArrivedListener listener);}
    • 在BookService中实现这两个方法,如下:
     @Override        public void registerNewBookArrivedListener(IONewBookArrivedListener listener) throws RemoteException {            if (listenerList.contains(listener)) {                Log.i(TAG, "listener already existe");            } else {                listenerList.add(listener);                Log.i(TAG, "register listener succsss");            }        }        @Override        public void unRegisterNewBookArrivedListener(IONewBookArrivedListener listener) throws RemoteException {            if (listenerList.contains(listener)) {                listenerList.remove(listener);                Log.i(TAG, "unRegister listener success");            } else {                Log.i(TAG, "not found listener");            }        }
    • 同时在BookService中开启一个线程,每隔五秒添加一本书,如下
     private class WorkService implements Runnable {        @Override        public void run() {            while (!mIsServiceDestoryed.get()) {                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                Book book = new Book(bookList.size() + 1, "new book" + bookList.size());                try {                    onNewBookArrived(book);                } catch (RemoteException e) {                    e.printStackTrace();                }            }        }    }    private void onNewBookArrived(Book book) throws RemoteException {        bookList.add(book);        for (IONewBookArrivedListener listener : listenerList) {            listener.onNewBookArrived(book);        }    }
  • 客户端
    • 首先将刚才定义的aidl文件拷贝到客户端相同目录下
    • 在绑定服务成功后,进行注册监听,如下
    private IONewBookArrivedListener listener = new IONewBookArrivedListener.Stub() {        @Override        public void onNewBookArrived(Book book) throws RemoteException {            Log.i(TAG, "onNewBookArrived : " + book.toString());        }    };    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mBookManager = IBookManager.Stub.asInterface(service);            try {                mBookManager.registerNewBookArrivedListener(listener);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            mBookManager = null;        }    };
    • 在onDestory方法中进行解绑监听和服务,如下:
    @Override    protected void onDestroy() {        super.onDestroy();        if (mBookManager != null && mBookManager.asBinder().isBinderAlive()) {            try {                mBookManager.unRegisterNewBookArrivedListener(listener);            } catch (RemoteException e) {                e.printStackTrace();            }        }        unbindService(conn);    }
  • 通过log日志查看,发现达到预期,每隔五秒添加一本新书并通知客户端,并且可以进行监听的动态注册和解绑,如下:
  • 但是,在activity关闭,进行注册监听解绑的时候,却发现log日志为这是为什么呢,下篇进行讲述吧。
  • 另外,服务端回调客户端的onBookArrived方法,是在客户端的Binder线程池中进行的,这里应该通过Handler将其发送到客户端的主线程中去执行,修改后代码如下:
    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MESSAGE_BOOK_ARRIVED:                    Log.i(TAG, "onNewBookArrived : " + msg.obj.toString());                    break;            }        }    };    private IONewBookArrivedListener listener = new IONewBookArrivedListener.Stub() {        @Override        public void onNewBookArrived(Book book) throws RemoteException {            mHandler.obtainMessage(MESSAGE_BOOK_ARRIVED, book).sendToTarget();        }    };

0 0
原创粉丝点击