IPC/RPC 提供對遠(yuǎn)端 Stub 對象狀態(tài)的訂閱機制,?在遠(yuǎn)端 Stub 對象消亡時,可觸發(fā)消亡通知告訴本地 Proxy 對象。這種狀態(tài)通知訂閱需要調(diào)用特定接口完成,當(dāng)不再需要訂閱時也需要調(diào)用特定接口取消。使用這種訂閱機制的用戶,需要實現(xiàn)消亡通知接口 DeathRecipient 并實現(xiàn) onRemoteDied 方法清理資源。該方法會在遠(yuǎn)端 Stub 對象所在進(jìn)程消亡或所在設(shè)備離開組網(wǎng)時被回調(diào)。值得注意的是,調(diào)用這些接口有一定的順序。首先,需要 Proxy 訂閱 Stub 消亡通知,若在訂閱期間 Stub 狀態(tài)正常,則在不再需要時取消訂閱;若在訂閱期間 Stub 所在進(jìn)程退出或者所在設(shè)備退出組網(wǎng),則會自動觸發(fā) Proxy 自定義的后續(xù)操作。
使用場景
這種訂閱機制適用于本地 Proxy 對象需要感知遠(yuǎn)端 Stub 對象所在進(jìn)程消亡,或所在設(shè)備離開組網(wǎng)的場景。當(dāng) Proxy 感知到 Stub 端消亡后,可適當(dāng)清理本地資源。此外,RPC 目前不提供匿名 Stub 對象的消亡通知,即只有向 SAMgr 注冊過的服務(wù)才能被訂閱消亡通知,IPC 則支持匿名對象的消亡通知。
Native 側(cè)接口
參考代碼 ?
#include "iremote_broker.h"
#include "iremote_stub.h"
//定義消息碼
enum {
TRANS_ID_PING_ABILITY = 5,
TRANS_ID_REVERSED_MONITOR
};
const std::string DESCRIPTOR = "test.ITestAbility";
class ITestService : public IRemoteBroker {
public:
// DECLARE_INTERFACE_DESCRIPTOR是必需的,入?yún)⑿枋褂胹td::u16string;
DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));
virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定義業(yè)務(wù)函數(shù)
};
class TestServiceProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
virtual int TestPingAbility(const std::u16string &dummy) override;
int TestAnonymousStub();
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便后續(xù)使用iface_cast宏
};
TestServiceProxy::TestServiceProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(impl)
{
}
int TestServiceProxy::TestPingAbility(const std::u16string &dummy){
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.WriteString16(dummy);
int error = PeerHolder::Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
#include "iremote_object.h"
class TestDeathRecipient : public IRemoteObject::DeathRecipient {
public:
virtual void OnRemoteDied(const wptr<IRemoteObject>& remoteObject);
}
void TestDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
{
}
sptr<IPCObjectProxy> object = new IPCObjectProxy(1, to_utf16(DESCRIPTOR));
sptr<IRemoteObject::DeathRecipient> deathRecipient (new TestDeathRecipient());// 構(gòu)造一個消亡通知對象
bool result = object->AddDeathRecipient(deathRecipient); // 注冊消亡通知
result = object->RemoveDeathRecipient(deathRecipient); // 移除消亡通知
JS 側(cè)接口
參考代碼
import FA from "@ohos.ability.featureAbility";
let proxy;
let connect = {
onConnect: function(elementName, remoteProxy) {
console.log("RpcClient: js onConnect called.");
proxy = remoteProxy;
},
onDisconnect: function(elementName) {
console.log("RpcClient: onDisconnect");
},
onFailed: function() {
console.log("RpcClient: onFailed");
}
};
let want = {
"bundleName": "com.ohos.server",
"abilityName": "com.ohos.server.MainAbility",
};
FA.connectAbility(want, connect);
class MyDeathRecipient {
onRemoteDied() {
console.log("server died");
}
}
let deathRecipient = new MyDeathRecipient();
proxy.addDeathRecipient(deathRecipient, 0);
proxy.removeDeathRecipient(deathRecipient, 0);
Stub 感知 Proxy 消亡(匿名 Stub 的使用)
正向的消亡通知是 Proxy 感知 Stub 的狀態(tài),若想達(dá)到反向的死消亡通知,即 Stub 感知 Proxy 的狀態(tài),可以巧妙的利用正向消亡通知。如兩個進(jìn)程 A(原 Stub 所在進(jìn)程)和 B(原 Proxy 所在進(jìn)程),進(jìn)程 B 在獲取到進(jìn)程 A 的 Proxy 對象后,在 B 進(jìn)程新建一個匿名 Stub 對象(匿名指未向 SAMgr 注冊),可稱之為回調(diào) Stub,再通過 SendRequest 接口將回調(diào) Stub 傳給進(jìn)程 A 的原 Stub。這樣一來,進(jìn)程 A 便獲取到了進(jìn)程 B 的回調(diào) Proxy。當(dāng)進(jìn)程 B 消亡或 B 所在設(shè)備離開組網(wǎng)時,回調(diào) Stub 會消亡,回調(diào) Proxy 會感知,進(jìn)而通知給原 Stub,便實現(xiàn)了反向消亡通知。
注意:
反向死亡通知僅限設(shè)備內(nèi)跨進(jìn)程通信使用,不可用于跨設(shè)備。文章來源:http://www.zghlxwxcb.cn/news/detail-724757.html
當(dāng)匿名 Stub 對象沒有被任何一個 Proxy 指向的時候,內(nèi)核會自動回收。文章來源地址http://www.zghlxwxcb.cn/news/detail-724757.html
參考代碼
//Proxy
int TestAbilityProxy::TestAnonymousStub()
{
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.UpdateDataVersion(Remote());
dataParcel.WriteRemoteObject(new TestAbilityStub());
int error = Remote()->SendRequest(TRANS_ID_REVERSED_MONITOR,dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
//Stub
int TestAbilityStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
switch (code) {
case TRANS_ID_REVERSED_MONITOR: {
sptr<IRemoteObject> obj = data.ReadRemoteObject();
if (obj == nullptr) {
reply.WriteInt32(ERR_NULL_OBJECT);
return ERR_NULL_OBJECT;
}
bool result = obj->AddDeathRecipient(new TestDeathRecipient());
result ? reply.WriteInt32(ERR_NONE) : reply.WriteInt32(-1);
break;
}
default:
break;
}
return ERR_NONE;
}
到了這里,關(guān)于HarmonyOS 遠(yuǎn)端狀態(tài)訂閱開發(fā)實例的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!