iremoteObject --------OpenHarmony中跨进程注册的observer 原创 精华
iremoteObject --------OpenHarmony中跨进程注册的observer
概述
一般来说,我们在编写代码的时候,经常遇到回调接口需要注册的情况,在单进程之中,我们经常是函数指针传给调用者。那跨进程的场景是如何操作的呢?答案就是iremoteObject。
以标准系统蓝牙代码为例
最近根据工作的要求,学习研究蓝牙相关代码。通过源码,我们理解学习了针对蓝牙服务,多事件监听的设计模式。
.
├── bluetooth_a2dp_sink_observer_proxy.h
├── bluetooth_a2dp_sink_observer_stub.h
├── bluetooth_a2dp_sink_proxy.h
├── bluetooth_a2dp_sink_stub.h
├── bluetooth_a2dp_src_observer_proxy.h
├── bluetooth_a2dp_src_observer_stub.h
├── bluetooth_a2dp_src_proxy.h
├── bluetooth_a2dp_src_stub.h
├── bluetooth_avrcp_ct_observer_proxy.h
├── bluetooth_avrcp_ct_observer_stub.h
├── bluetooth_avrcp_ct_proxy.h
├── bluetooth_avrcp_ct_stub.h
├── bluetooth_avrcp_tg_observer_proxy.h
├── bluetooth_avrcp_tg_observer_stub.h
├── bluetooth_avrcp_tg_proxy.h
├── bluetooth_avrcp_tg_stub.h
├── bluetooth_ble_advertise_callback_proxy.h
├── bluetooth_ble_advertise_callback_stub.h
├── bluetooth_ble_advertiser_proxy.h
├── bluetooth_ble_advertiser_stub.h
├── bluetooth_ble_central_manager_callback_proxy.h
├── bluetooth_ble_central_manager_callback_stub.h
├── bluetooth_ble_central_manager_proxy.h
├── bluetooth_ble_central_manager_stub.h
├── bluetooth_ble_peripheral_observer_proxy.h
├── bluetooth_ble_peripheral_observer_stub.h
├── bluetooth_gatt_client_callback_proxy.h
├── bluetooth_gatt_client_callback_stub.h
...
还是经典的proxy -stub架构。为了更好理解本文相关的内容,建议阅读 https://ost.51cto.com/posts/10765
我们截取其中的一部分来分析。
├── bluetooth_a2dp_sink_observer_proxy.h
├── bluetooth_a2dp_sink_observer_stub.h
├── bluetooth_a2dp_sink_proxy.h
├── bluetooth_a2dp_sink_stub.h
咋一眼,和iremoteObject无关啊。a2dp是蓝牙音频传输的相关内容,sink是指的是控制端。这里我们不需要关注这个问题。我们还是通过源码看是如何跨进程注册的。
void BluetoothA2dpSinkProxy::RegisterObserver(const sptr<IBluetoothA2dpSinkObserver> &observer)
{
MessageParcel data;
if (!data.WriteInterfaceToken(BluetoothA2dpSinkProxy::GetDescriptor())) {
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver WriteInterfaceToken error");
return;
}
if (!data.WriteRemoteObject(observer->AsObject())) { // 就是将对象进行传输
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver error");
return;
}
MessageParcel reply;
MessageOption option {
MessageOption::TF_ASYNC
};
int error = Remote()->SendRequest(IBluetoothA2dpSink::Code::BT_A2DP_SINK_REGISTER_OBSERVER, data, reply, option);
if (error != NO_ERROR) {
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver done fail, error: %{public}d", error);
return;
}
}
从上面可以看出 proxy通过写observer 对象到data中,然后再通过sendRequest发送到对端。那对端一般怎么做呢?对端一般是服务,也是真正的监听者 。到这里,其实我们也可以猜到个大概,使用std::bind转化对端发来的对象(或接口)注册到真正的事件监听中。(这个observer其实是对象也是接口,继承至iremoteBroker属于接口,继承至iremoteObject是对象。)
void BluetoothA2dpSinkServer::RegisterObserver(const sptr<IBluetoothA2dpSinkObserver> &observer)
{
HILOGI("BluetoothA2dpSinkServer::RegisterObserver starts");
if (observer == nullptr) {
HILOGI("BluetoothA2dpSinkServer::RegisterObserver observer is null");
return;
}
pimpl->observers_.Register(observer);
}
stub 中没有直接实现,他的子类BluetoothA2dpSinkServer去实现了。而真正的实现交给了pimpl->observers_它。
Observer真正触发
上文中说了半天,这个iremote对象注册了有什么用呢?当你的observer(proxy)注册到服务的(stub)中,服务中真正的触发了,被注册的observer(proxy),调用相关函数,sendRequest发送到proxy 中的stub中,触发真正的回调。 纵观整个过程通过binder驱动,发送消息,就好像observer注册到自身进程之中。
概述
一般来说,我们在编写代码的时候,经常遇到回调接口需要注册的情况,在单进程之中,我们经常是函数指针传给调用者。那跨进程的场景是如何操作的呢?答案就是iremoteObject。
以标准系统蓝牙代码为例
最近根据工作的要求,学习研究蓝牙相关代码。通过源码,我们理解学习了针对蓝牙服务,多事件监听的设计模式。
.
├── bluetooth_a2dp_sink_observer_proxy.h
├── bluetooth_a2dp_sink_observer_stub.h
├── bluetooth_a2dp_sink_proxy.h
├── bluetooth_a2dp_sink_stub.h
├── bluetooth_a2dp_src_observer_proxy.h
├── bluetooth_a2dp_src_observer_stub.h
├── bluetooth_a2dp_src_proxy.h
├── bluetooth_a2dp_src_stub.h
├── bluetooth_avrcp_ct_observer_proxy.h
├── bluetooth_avrcp_ct_observer_stub.h
├── bluetooth_avrcp_ct_proxy.h
├── bluetooth_avrcp_ct_stub.h
├── bluetooth_avrcp_tg_observer_proxy.h
├── bluetooth_avrcp_tg_observer_stub.h
├── bluetooth_avrcp_tg_proxy.h
├── bluetooth_avrcp_tg_stub.h
├── bluetooth_ble_advertise_callback_proxy.h
├── bluetooth_ble_advertise_callback_stub.h
├── bluetooth_ble_advertiser_proxy.h
├── bluetooth_ble_advertiser_stub.h
├── bluetooth_ble_central_manager_callback_proxy.h
├── bluetooth_ble_central_manager_callback_stub.h
├── bluetooth_ble_central_manager_proxy.h
├── bluetooth_ble_central_manager_stub.h
├── bluetooth_ble_peripheral_observer_proxy.h
├── bluetooth_ble_peripheral_observer_stub.h
├── bluetooth_gatt_client_callback_proxy.h
├── bluetooth_gatt_client_callback_stub.h
...
还是经典的proxy -stub架构。为了更好理解本文相关的内容,建议阅读 https://ost.51cto.com/posts/10765
我们截取其中的一部分来分析。
├── bluetooth_a2dp_sink_observer_proxy.h
├── bluetooth_a2dp_sink_observer_stub.h
├── bluetooth_a2dp_sink_proxy.h
├── bluetooth_a2dp_sink_stub.h
咋一眼,和iremoteObject无关啊。a2dp是蓝牙音频传输的相关内容,sink是指的是控制端。这里我们不需要关注这个问题。我们还是通过源码看是如何跨进程注册的。
void BluetoothA2dpSinkProxy::RegisterObserver(const sptr<IBluetoothA2dpSinkObserver> &observer)
{
MessageParcel data;
if (!data.WriteInterfaceToken(BluetoothA2dpSinkProxy::GetDescriptor())) {
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver WriteInterfaceToken error");
return;
}
if (!data.WriteRemoteObject(observer->AsObject())) { // 就是将对象进行传输
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver error");
return;
}
MessageParcel reply;
MessageOption option {
MessageOption::TF_ASYNC
};
int error = Remote()->SendRequest(IBluetoothA2dpSink::Code::BT_A2DP_SINK_REGISTER_OBSERVER, data, reply, option);
if (error != NO_ERROR) {
HILOGE("BluetoothA2dpSinkProxy::RegisterObserver done fail, error: %{public}d", error);
return;
}
}
从上面可以看出 proxy通过写observer 对象到data中,然后再通过sendRequest发送到对端。那对端一般怎么做呢?对端一般是服务,也是真正的监听者 。到这里,其实我们也可以猜到个大概,使用std::bind转化对端发来的对象(或接口)注册到真正的事件监听中。(这个observer其实是对象也是接口,继承至iremoteBroker属于接口,继承至iremoteObject是对象。)
void BluetoothA2dpSinkServer::RegisterObserver(const sptr<IBluetoothA2dpSinkObserver> &observer)
{
HILOGI("BluetoothA2dpSinkServer::RegisterObserver starts");
if (observer == nullptr) {
HILOGI("BluetoothA2dpSinkServer::RegisterObserver observer is null");
return;
}
pimpl->observers_.Register(observer);
}
stub 中没有直接实现,他的子类BluetoothA2dpSinkServer去实现了。而真正的实现交给了pimpl->observers_它。
Observer真正触发
上文中说了半天,这个iremote对象注册了有什么用呢?当你的observer(proxy)注册到服务的(stub)中,服务中真正的触发了,被注册的observer(proxy),调用相关函数,sendRequest发送到proxy 中的stub中,触发真正的回调。 纵观整个过程通过binder驱动,发送消息,就好像observer注册到自身进程之中。
感谢老师分享。
666
牛逼,大神之作