AIDL使用 进阶2

使用aidl 后如何彼此检测远程服务和客户端的生命周期。如果不能监控那将有一个很严重问题,程序可能会出现Crash ,报的基本是一个远程服务已经不存在。

1.客户端如何检测服务端是否连接

基本有三种方式:

  • 调用远程方法的时候捕获RemoteException(DeadObjectException);
  • 调用IBinder的pingBinder()进行检测;
  • 实现IBinder.DeathRecipient接口回调

前两种是比较被动的,一般是你去使用的时候才去调用和验证。

相比第三种比较靠谱些。

基本使用就是将

onServiceConnected 方法的参数IBinder 注册监听器
service.linkToDeath (new IBinder.DeathRecipient () {
    @Override
    public void binderDied() {
        
    }
},0);

当远程服务端异常终止或者死亡时就会触发binderDied。

2.服务端如何监控客户端注册的接口的生命

方法基本有四种:

  • 调用远程方法的时候捕获RemoteException(DeadObjectException);
  • 调用IBinder的pingBinder()进行检测;
  • 监控客户端的服务的生命周期比如unBind()
  • 通过RemoteCallbackList 来监控

前两种方式是比较被动的,通过组合判断的方式,也可以知道当前注册的客户端的接口是否已不在存活。

第三种方式按道理也可以,但是在实践中发现有些特殊场景unBind 是不会执行的,所以这就注定了这种方案行不通。

重点讲RemoteCallbackList

将客户端注册的接口类添加到RemoteCallbackList 集合中

比如

private final static RemoteCallbackList<IDeviceObserver> mEventObservers = new RemoteCallbackList<> ();
protected synchronized static void addObserver(IDeviceObserverobserver) {
    mEventObservers .register (observer);
}

protected synchronized static void removeObserver(IDeviceObserverobserver) {
    mEventObservers .unregister (observer);
}

触发回掉函数


        int remoteClients = mEventObservers.beginBroadcast ();
      
        try {
            for (int i = 0; i < remoteClients; i++) {
                mEventObservers.getBroadcastItem (i).onDeviceEvent (parcelProxy);
            }
        } catch (RemoteException e) {
            Log.e (TAG, Log.getStackTraceString (e));
        }
        mEventObservers.finishBroadcast ();

这里的onDeviceEvent 就是IDeviceObserver 客户端注册接口的方法,执行完上述代码后就触发了客户端的回掉。

但是这里有个坑,这个操作必须保持同步操作,也就是调用beginBroadcast 到调用finishBroadcast,不能中断或者过程中再调用finishBroadcast ,否则会报

 throw new IllegalStateException(
                        "beginBroadcast() called while already in a broadcast");

或者

 throw new IllegalStateException(
                        "finishBroadcast() called outside of a broadcast");

3. AIDL 中 in  out    inout 使用

IN :代表输入,被in 标识过的对象只能由写入端(简称client)修改,对端(service)收到对象修改后不能改变写入端client 数据(改变后client 不会改变),相当于service 收到了一份克隆后的数据,client 数据改变service 并不能感知,只能被动接受client数据。

OUT: 代表输出,被out 标识过的 client 对象,client 调用接口传递数据到service改数 ,也就是在服务端执行方法的时候,并不会去读取客户端的这个参数,而是自己new一个新对象,用此新对象来作为参数执行方法。但是在方法执行完之后,会把这个参数又传回客户端,更新客户端的对象参数值。也就是service 数据改变client 并不能感知,只能被动接受service 改变后的值。

INOUT: 表示两端都可以修改,并且数据内容会在client 和service 两端同步,相互之间都是可以传递和感知的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值