# 远端状æ€è®¢é˜…å¼€å‘实例 IPC/RPCæä¾›å¯¹è¿œç«¯Stub对象状æ€çš„订阅机制,在远端Stub对象消亡时,å¯è§¦å‘消亡通知告诉本地Proxy对象。这ç§çжæ€é€šçŸ¥è®¢é˜…需è¦è°ƒç”¨ç‰¹å®šæŽ¥å£å®Œæˆï¼Œå½“ä¸å†éœ€è¦è®¢é˜…时也需è¦è°ƒç”¨ç‰¹å®šæŽ¥å£å–消。使用这ç§è®¢é˜…机制的用户,需è¦å®žçŽ°æ¶ˆäº¡é€šçŸ¥æŽ¥å£DeathRecipient并实现onRemoteDied方法清ç†èµ„æºã€‚该方法会在远端Stub对象所在进程消亡或所在设备离开组网时被回调。值得注æ„çš„æ˜¯ï¼Œè°ƒç”¨è¿™äº›æŽ¥å£æœ‰ä¸€å®šçš„顺åºã€‚首先,需è¦Proxy订阅Stub消亡通知,若在订阅期间StubçŠ¶æ€æ£å¸¸ï¼Œåˆ™åœ¨ä¸å†éœ€è¦æ—¶å–消订阅;若在订阅期间Stub所在进程退出或者所在设备退出组网,则会自动触å‘Proxy自定义的åŽç»æ“作。 ## 使用场景 è¿™ç§è®¢é˜…机制适用于本地Proxyå¯¹è±¡éœ€è¦æ„ŸçŸ¥è¿œç«¯Stub对象所在进程消亡,或所在设备离开组网的场景。当Proxy感知到Stub端消亡åŽï¼Œå¯é€‚å½“æ¸…ç†æœ¬åœ°èµ„æºã€‚æ¤å¤–,RPCç›®å‰ä¸æä¾›åŒ¿åStub对象的消亡通知,å³åªæœ‰å‘SAMgr注册过的æœåŠ¡æ‰èƒ½è¢«è®¢é˜…消亡通知,IPC则支æŒåŒ¿å对象的消亡通知。 <!--Del--> ## Nativeä¾§æŽ¥å£ | 接å£å | æè¿° | | ------------------------------------------------------------------- | ------------------------- | | bool AddDeathRecipient(const sptr\<DeathRecipient> &recipient); | 订阅远端Stub对象状æ€ã€‚ | | bool RemoveDeathRecipient(const sptr\<DeathRecipient> &recipient); | å–æ¶ˆè®¢é˜…远端Stub对象状æ€ã€‚ | | void OnRemoteDied(const wptr\<IRemoteObject> &object); | 当远端Stub对象æ»äº¡æ—¶å›žè°ƒã€‚ | ### å‚考代ç ```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是必需的,入å‚需使用std::u16stringï¼› DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR)); virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数 }; 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_; // 方便åŽç»ä½¿ç”¨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; } ``` ```C++ #include "iremote_object.h" class TestDeathRecipient : public IRemoteObject::DeathRecipient { public: virtual void OnRemoteDied(const wptr<IRemoteObject>& remoteObject); } void TestDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject) { } ``` ```c++ sptr<IPCObjectProxy> object = new IPCObjectProxy(1, to_utf16(DESCRIPTOR)); sptr<IRemoteObject::DeathRecipient> deathRecipient (new TestDeathRecipient()); // æž„é€ ä¸€ä¸ªæ¶ˆäº¡é€šçŸ¥å¯¹è±¡ bool result = object->AddDeathRecipient(deathRecipient); // 注册消亡通知 result = object->RemoveDeathRecipient(deathRecipient); // 移除消亡通知 ``` <!--DelEnd--> ## ArkTSä¾§æŽ¥å£ > **说明:** > > - æ¤æ–‡æ¡£ä¸çš„ç¤ºä¾‹ä»£ç æè¿°çš„æ˜¯ç³»ç»Ÿåº”ç”¨è·¨è¿›ç¨‹é€šä¿¡ã€‚ > > - 当å‰ä¸æ”¯æŒä¸‰æ–¹åº”用实现ServiceExtensionAbility,三方应用的UIAbility组件å¯ä»¥é€šè¿‡Context连接系统æä¾›çš„ServiceExtensionAbility。 > > - 当å‰ä½¿ç”¨åœºæ™¯ï¼š ä»…é™å®¢æˆ·ç«¯æ˜¯ä¸‰æ–¹åº”用,æœåŠ¡ç«¯æ˜¯ç³»ç»Ÿåº”ç”¨ã€‚ | 接å£å | 返回值类型 | 功能æè¿° | | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ | | [registerDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#registerdeathrecipient9-1) | void | æ³¨å†Œç”¨äºŽæŽ¥æ”¶è¿œç¨‹å¯¹è±¡æ¶ˆäº¡é€šçŸ¥çš„å›žè°ƒï¼Œå¢žåŠ proxy 对象上的消亡通知。 | | [unregisterDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#unregisterdeathrecipient9-1) | void | 注销用于接收远程对象消亡通知的回调。 | | [onRemoteDied](../reference/apis-ipc-kit/js-apis-rpc.md#onremotedied) | void | 在æˆåŠŸæ·»åŠ æ»äº¡é€šçŸ¥è®¢é˜…åŽï¼Œå½“远端对象æ»äº¡æ—¶ï¼Œå°†è‡ªåŠ¨è°ƒç”¨æœ¬æ–¹æ³•ã€‚ | ### å‚考代ç ```ts // FA模型需è¦ä»Ž@kit.AbilityKit导入featureAbility // import { featureAbility } from '@kit.AbilityKit'; import { Want, common } from '@kit.AbilityKit'; import { rpc } from '@kit.IPCKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; let proxy: rpc.IRemoteObject | undefined; let connect: common.ConnectOptions = { onConnect: (elementName, remoteProxy) => { hilog.info(0x0000, 'testTag', 'RpcClient: js onConnect called.'); proxy = remoteProxy; }, onDisconnect: (elementName) => { hilog.info(0x0000, 'testTag', 'RpcClient: onDisconnect'); }, onFailed: () => { hilog.info(0x0000, 'testTag', 'RpcClient: onFailed'); } }; let want: Want = { bundleName: "com.ohos.server", abilityName: "com.ohos.server.EntryAbility", }; // FAæ¨¡åž‹é€šè¿‡æ¤æ–¹æ³•连接æœåŠ¡ // FA.connectAbility(want, connect); // 建立连接åŽè¿”回的Id需è¦ä¿å˜ä¸‹æ¥ï¼Œåœ¨è§£ç»‘æœåŠ¡æ—¶éœ€è¦ä½œä¸ºå‚æ•°ä¼ å…¥ let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext // 建立连接åŽè¿”回的Id需è¦ä¿å˜ä¸‹æ¥ï¼Œåœ¨è§£ç»‘æœåŠ¡æ—¶éœ€è¦ä½œä¸ºå‚æ•°ä¼ å…¥ let connectionId = context.connectServiceExtensionAbility(want, connect); ``` 上述onConnect回调函数ä¸çš„proxy对象需è¦ç‰ability异æ¥è¿žæŽ¥æˆåŠŸåŽæ‰ä¼šè¢«èµ‹å€¼ï¼Œç„¶åŽæ‰å¯è°ƒç”¨proxy对象的[unregisterDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#unregisterdeathrecipient9-1)æŽ¥å£æ–¹æ³•注销æ»äº¡å›žè°ƒ ```ts import { rpc } from '@kit.IPCKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; class MyDeathRecipient implements rpc.DeathRecipient{ onRemoteDied() { hilog.info(0x0000, 'testTag', 'server died'); } } let deathRecipient = new MyDeathRecipient(); if (proxy != undefined) { proxy.registerDeathRecipient(deathRecipient, 0); proxy.unregisterDeathRecipient(deathRecipient, 0); } ``` ## Stub感知Proxy消亡(匿åStub的使用) æ£å‘的消亡通知是Proxy感知Stub的状æ€ï¼Œè‹¥æƒ³è¾¾åˆ°åå‘çš„æ»æ¶ˆäº¡é€šçŸ¥ï¼Œå³Stub感知Proxy的状æ€ï¼Œå¯ä»¥å·§å¦™çš„利用æ£å‘消亡通知。如两个进程A(原Stub所在进程)和B(原Proxy所在进程),进程B在获å–到进程Açš„Proxy对象åŽï¼Œåœ¨B进程新建一个匿åStubå¯¹è±¡ï¼ˆåŒ¿åæŒ‡æœªå‘SAMgr注册),å¯ç§°ä¹‹ä¸ºå›žè°ƒStub,å†é€šè¿‡SendRequest接å£å°†å›žè°ƒStubä¼ ç»™è¿›ç¨‹A的原Stubã€‚è¿™æ ·ä¸€æ¥ï¼Œè¿›ç¨‹A便获å–到了进程B的回调Proxy。当进程B消亡或B所在设备离开组网时,回调Stub会消亡,回调Proxy会感知,进而通知给原Stub,便实现了å呿¶ˆäº¡é€šçŸ¥ã€‚ 注æ„: > å呿»äº¡é€šçŸ¥ä»…é™è®¾å¤‡å†…跨进程通信使用,ä¸å¯ç”¨äºŽè·¨è®¾å¤‡ã€‚ > 当匿åStub对象没有被任何一个Proxy指å‘çš„æ—¶å€™ï¼Œå†…æ ¸ä¼šè‡ªåŠ¨å›žæ”¶ã€‚ ### å‚考代ç ```c++ // 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; } ```