跨进程通信Binder执行耗时任务

在Binder机制中有客户端和服务端。通过定义AIDL文件,客户端可以拿到服务端的IBinder接口,从而直接调用服务端的AIDL方法;而服务端同样可以通过回调的方式,拿到客户端的AIDL方法进行回调。

所有的AIDL方法都是在服务端的Binder线程池中执行的,也就是说,每一个AIDL方法执行的时候都会在一个服务线程中执行。

比如,客户端(Activity)通过ServiceConnection拿到了服务端(一般是service)的IBookManager这个AIDL接口:

private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 绑定成功后将Binder对象转换成AIDL接口
            IBookManager bookManager = IBookManager.Stub.asInterface(service);
            try {
                mRemoteBookManager = bookManager;
                BookEntity bookEntity = new BookEntity("3", "Android AIDL");
                bookManager.addBook(bookEntity);
                List<BookEntity> list = bookManager.getBookList();
                for (BookEntity book : list) {
                    Logger.d(book.getBookId() + "," + book.getBookName());
                }
                bookManager.registerListener(mNewBookArrivedListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteBookManager = null;
        }
    };

同时通过这个接口向服务端注册了一个回调AIDL接口:NewBookArrivedListener

客户端通过IbookManager接口发起一次调用,消息发送到Binder驱动,客户端当前处理这个调用的线程(及主线程)被挂起,Binder驱动通知服务端执行这个任务,一旦服务端执行这个任务时间过长(也就是客户端被挂起的时间过长),那么就可能导致客户端出现了ANR(在主线程中执行时间过长)。服务端执行完任务后,返回结果给Binder驱动,Binder驱动唤醒客户端线程继续处理。


服务端(service)通过AIDL回调接口,主动通知客户端(即回调客户端的AIDL接口的方法),该方法会执行在客户端的一个新起的线程中(并不在UI线程),所以此时要更新UI操作,就要切换线程了。(不是很理解为什么新开了一个线程?)


另外,在服务端数据集合一般使用CopyOnWriteArrayList,该类是线程安全的。因为服务端是用一个Binder线程池来处理客户端的各种请求,会存在多个客户端同时访问服务端的情况,数据集合必须实现线程同步。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值