欢迎光临
我们一直在努力

鸿蒙开发:MessageParcel、MessageSequence 与 sendMessageRequest 实战避坑

很多初学者写鸿蒙 RPC 代码时,最容易出问题的地方不是连接服务,而是消息对象的读写细节。比如客户端 writeString、writeInt 的顺序和服务端 readString、readInt 不一致,就可能导致读到错误数据;异步调用时还想立刻从 reply 里取值,也会出现空结果。

所以第二篇我们专门拆 MessageParcel / MessageSequence、sendMessageRequest、DeathRecipient 和资源释放。把这些点弄清楚,RPC 代码就会稳定很多。

图 3  消息对象的读写顺序

1. MessageParcel 和 MessageSequence 怎么理解

对象

常见用途

注意事项

MessageParcel

旧接口或兼容场景中常见,用于读写基础类型、数组、远端对象等

部分 sendRequest 相关接口在新 API 中已不建议继续使用

MessageSequence

API 9+ 推荐与 sendMessageRequest 搭配使用

客户端和服务端要严格保持字段顺序、类型和接口令牌一致

MessageOption

声明同步或异步调用模式

异步模式下 reply 通常不能按同步返回值理解

MessageSequence 的思路可以类比一个顺序队列:写入端按 A、B、C 放进去,读取端也必须按 A、B、C 取出来。它不会自动根据字段名匹配,也不会帮你判断“这里本来应该是 string”。因此,RPC 协议最怕两端代码各改各的:客户端多写了一个字段,服务端没有同步读取,后面的字段就会全部错位。

如果传输的是复杂对象,建议先把字段拆成基础类型,或者把对象序列化成 JSON 字符串,并在 JSON 中携带 version。基础类型适合高频、小数据量调用;JSON 适合字段经常变化但体积不大的业务对象;如果是大文件、图片、视频,不建议直接塞进 RPC 消息里,更适合传文件描述符、URI 或通过专门的传输通道处理。

2. 服务端处理请求的模板

class BookRemoteObject extends rpc.RemoteObject {

  constructor() { super('com.demo.BookService'); }

  onRemoteMessageRequest(code: number, data: rpc.MessageSequence,

    reply: rpc.MessageSequence, option: rpc.MessageOption): boolean {

    if (code === REQUEST_GET_BOOK) {

      data.readInterfaceToken();

      let bookId = data.readString();

      reply.writeNoException();

      reply.writeString('HarmonyOS RPC Guide: ' + bookId);

      return true;

    }

    return false;

  }

}

3. sendMessageRequest 的同步和异步

官方接口里 MessageOption 可以声明调用模式。同步模式更像普通函数调用:客户端等待服务端处理完,再从 reply 中读取结果。它适合“查询配置”“读取小段状态”“校验一个值”这种短耗时任务。异步模式更适合长耗时任务或跨设备调用,客户端不应该立刻依赖 reply,而是通过回调对象、事件通知或状态查询拿最终结果。

选择同步还是异步,核心看两个问题:业务结果是不是马上要用,服务端处理会不会阻塞。如果页面点击按钮后必须立即展示结果,并且服务端只做轻量计算,可以用同步;如果服务端要扫描设备、上传文件、等待网络响应,就应当用异步。否则用户会感觉界面卡住,严重时还可能触发超时或进程调度问题。

4. 为什么要 reclaim

消息对象底层涉及跨进程通信缓冲区,不应该等垃圾回收器慢慢处理。实践中建议把 data、reply 的释放写进 finally,保证成功、失败、异常路径都会执行。这样做不仅代码整洁,也能避免高频调用时出现资源占用累积。

同样重要的是异常路径。很多示例代码只写 then 里的成功读取,但真实业务中要同时处理 sendMessageRequest 本身失败、服务端写入异常、readException 读到远端异常、reply 字段为空等情况。把这些异常统一封装成业务错误,再返回给 UI 层,会比在页面里到处 try/catch 更可维护。

5. 常见问题排查表

现象

可能原因

建议处理

服务端收不到请求

未连接成功、IRemoteObject 为空、请求码不一致

先打印 onConnect,再统一维护请求码常量

读取参数错位

write/read 顺序或类型不一致

把接口协议写成固定模板,客户端和服务端共用定义

异步调用没有返回值

把异步模式当同步模式使用

确认 MessageOption 模式,异步结果走回调或业务通知

服务重启后调用失败

客户端持有的远端对象已死亡

注册 DeathRecipient,死亡后重新连接服务

6. 推荐写法清单

  • 请求码使用常量集中管理,不要在多处手写数字。
  • 每个接口先写 interface token,服务端先校验 token,再处理业务参数。
  • 读写字段顺序写进注释或 IDL,不要靠记忆维护协议。
  • Promise / callback 中处理 errCode 和 readException,不要只写成功路径。
  • finally 中 reclaim 消息对象,死亡通知中清空代理并触发重连。

7. DeathRecipient 什么时候需要

当服务进程被系统回收、崩溃、升级重启,或者分布式设备离线时,客户端手里的远端对象就可能失效。DeathRecipient 的作用就是让客户端知道“这个远端对象已经死了”。收到通知后,最稳的处理方式不是继续重试同一个对象,而是清空缓存代理、提示业务层进入未连接状态,并按连接流程重新获取远端对象。

如果业务是一次性短调用,死亡通知可能不是必须;如果业务是长连接、设备控制、后台同步、持续订阅,就很有必要注册。注册后也别忘了在不再需要时注销,否则生命周期管理会变得混乱。可以把注册和注销放进连接管理器里,而不是散落在每个页面。

8. 小结

鸿蒙 RPC 的写法看起来是 API 调用,底层却是严格的消息协议。稳定的 RPC 代码通常有三个特征:协议常量清晰、消息读写对称、异常和生命周期处理完整。掌握这三点,再去看官方 @ohos.rpc 文档,很多接口就能自然串起来。

参考资料

  • HarmonyOS 官方文档:@ohos.rpc (RPC) API 参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-rpc
  • HarmonyOS 官方文档:ServiceExtensionAbility 开发参考:https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/app-service-extension-ability
  • HarmonyOS 文档中心:IPC Kit / Ability Kit 等开发文档入口:https://developer.huawei.com/consumer/cn/doc/
  • 参考写作风格:CSDN 技术博客式的“概念拆解 + 图示 + 表格 + 代码 + 总结”结构。
赞(0)
未经允许不得转载:171主机测评 » 鸿蒙开发:MessageParcel、MessageSequence 与 sendMessageRequest 实战避坑
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址