HarmonyOS —— 使用 URPC 进行远程程序调用实战笔记
HarmonyOS —— 使用 URPC 进行远程程序调用实战笔记
Remote Communication Kit 里前面都是 HTTP/Session 的玩法,
这一节换个路子:直接用 URPC(Unified Remote Procedure Call)做“远程函数调用”。
可以把 URPC 理解成:
“我在本地像调一个函数一样写
call("uploadFile", req, resp),
实际上是通过网络把请求丢给远端服务,拿回来一个响应对象。”
一、URPC 能力 & 设备支持快速扫一眼
功能关键词:
- 远程过程调用(Remote Procedure Call)
- 支持:
- 设置 调用优先级(
priority) - 使用 Promise 异步回调
- 支持 取消正在进行的调用
- 支持 销毁 Stub 释放资源
- 设置 调用优先级(
设备 & 版本:
- 支持:Phone / 2in1 / Tablet / Wearable
- 自 5.1.1(19) 起:新增支持 TV
一句话背:
URPC 远程程序调用能力支持 Phone / 2in1 / Tablet / Wearable,5.1.1(19) 起新增 TV 支持。
二、URPC 核心接口一览
URPC 的核心逻辑都围绕一个 UrpcStub 对象展开,常用 3 个方法:
call(
funcName: string,
request: object,
returnValue: object,
config?: CallingOption
): UrpcPromise
- 发送一个 URPC 请求;
funcName:远程服务端定义的方法名,比如"uploadFile";request:请求入参对象;returnValue:用于承接返回数据的对象(类实例);config:调用配置(例如priority);- 返回
UrpcPromise,里面带.promise和callingId。
cancel(callingId?: number | number[]): void
- 取消 指定 或 全部 正在进行中的 URPC 请求;
- 不传
callingId→ 取消当前 Stub 发起的所有请求。
destroy(): void
- 用完之后销毁
UrpcStub实例,释放关联资源。
三、完整调用流程拆解(从定义消息到销毁 Stub)
1. 导入模块
import { hilog } from "@kit.PerformanceAnalysisKit";
import { urpc } from "@kit.RemoteCommunicationKit";
import { BusinessError } from '@kit.BasicServicesKit';
urpc:URPC 主角;hilog:日志输出;BusinessError:异常统一用这个封装。
2. 定义 Request / Response 消息类
这里基于 urpc.FlowbufElement<T> 来描述一个字段:
// 请求消息
export class MediaTaskRequestMessage {
RequestMessage: urpc.FlowbufElement<string>;
constructor() {
this.RequestMessage = { type: 'STRING', value: "", name: "" };
}
setRequestMessage(RequestMessage: string) {
this.RequestMessage.value = RequestMessage;
}
getRequestMessage(): string {
return this.RequestMessage.value;
}
}
// 响应消息
export class MediaTaskResponseMessage {
ResponseMessage: urpc.FlowbufElement<string>;
constructor() {
this.ResponseMessage = { type: 'STRING', value: "", name: "" };
}
setResponseMessage(ResponseMessage: string) {
this.ResponseMessage.value = ResponseMessage;
}
getResponseMessage(): string {
return this.ResponseMessage.value;
}
}
要点:
- 每个字段用
FlowbufElement<T>包裹,指定:type:类型(如'STRING');value:实际值;name:字段名(可在协议里用)。
- 把
setXxx / getXxx封装好,后面调用更顺手。
3. 创建 Request / Response 实例
let request = new MediaTaskRequestMessage();
let response = new MediaTaskResponseMessage();
// 比如这里设置请求内容
request.setRequestMessage("hello urpc");
- 请求对象 = 要发给远端的参数;
- 响应对象 = 用来接收返回数据。
4. 配置连接信息 & 创建 UrpcStub
let node: urpc.IpAndPort = {
ip: '127.0.0.1',
port: 8000
};
let connect: urpc.UrpcConnectConfiguration = {
node: node,
protocol: 'eat', // 协议字符串,需与服务端约定一致
};
let config: urpc.UrpcInitConfiguration = {
timeout: 3000, // 初始化超时时间
mode: 'client', // 当前为客户端模式
connect: connect
};
// 允许调用的远程函数列表
const funcList: string[] = ["uploadFile"];
// 创建 urpcStub(注意,返回的是 Promise)
let urpcStub = urpc.urpcStubCreate(config, funcList);
要点:
node指明 远端 IP + 端口;protocol需要与你的 URPC 服务端实现保持一致(如'eat');funcList里是你允许客户端调用的 远程方法名列表,比如"uploadFile";urpcStubCreate返回的是一个 Promise,所以后续要 .then(...)。
5. 使用 call 发送 URPC 请求
urpcStub.then(async (stub: urpc.UrpcStub) => {
let upload_config: urpc.CallingOption = {
priority: 0 // 优先级,数字越小可能表示越高优先
};
let urpcPromise = stub.call("uploadFile", request, response, upload_config);
urpcPromise.promise
.then((resp: object) => {
hilog.info(0x000, "urpc", "resp: %{public}s", resp);
// 一般会从 response 对象里再用 getResponseMessage() 拿业务数据
})
.catch((err: BusinessError) => {
hilog.error(0x000, "urpc", "the error code is %d", err.code);
});
}).catch((error: BusinessError) => {
hilog.error(0x000, "urpc", "urpc call failed, error code is %d", error.code);
});
这里有两个“Promise 层”:
urpcStub自身是Promise<UrpcStub>;stub.call(...)返回的是UrpcPromise,里面还有一个.promise真正表示这次远程调用的完成/失败。
CallingOption 里可以配置:
priority:请求优先级(数值约定视服务端实现而定)。
6. 使用 cancel 取消请求(可选)
有时候发出请求后发现 不需要结果了(页面退出、用户取消、超时兜底逻辑等),就可以手动取消:
urpcStub.then(async (stub: urpc.UrpcStub) => {
let upload_config: urpc.CallingOption = {
priority: 0
};
let urpcPromise = stub.call("uploadFile", request, response, upload_config);
// 取消指定 callingId 对应的这一次调用
stub.cancel(urpcPromise.callingId);
}).catch((error: BusinessError) => {
hilog.error(0x000, "urpc", "urpc cancel failed, error code is %d", error.code);
});
- 传入单个
callingId→ 取消该次请求; - 传入
number[]→ 一次性取消多个; - 不传参数 → 取消当前 Stub 下所有正在进行的调用。
7. 使用 destroy 释放资源(必做收尾)
当这个 Stub 不再需要继续发请求时,要记得销毁它:
urpcStub.then(async (stub: urpc.UrpcStub) => {
stub.destroy();
}).catch((error: BusinessError) => {
hilog.error(0x000, "urpc", "urpc destroy failed, error code is %d", error.code);
});
- 释放连接、内部缓冲等资源;
- 一般可以在:
- 页面销毁时;
- 模块退出时;
- 或应用退出前集中调用。
四、实战 Tips & 常踩坑点
- 服务端方法名必须匹配
funcList里的"uploadFile"必须跟服务端暴露的远程函数名字一致;- 大小写也要一致,否则会直接调用失败。
- 入参/出参类要和服务端约定好结构
MediaTaskRequestMessage和MediaTaskResponseMessage的字段类型(FlowbufElement类型、字段name等)要和服务端协议对齐;- 否则就算网络调用成功,序列化/反序列化阶段也可能出错或拿不到正确数据。
- 注意超时配置
UrpcInitConfiguration.timeout只是初始化 Stub 时的超时;- 具体调用过程中的超时策略还可以在协议层或服务端进一步控制。
- cancel 不等于立即“秒停”
cancel是“请求取消语义”,底层是否已经发完 / 服务器是否已经处理完,会根据实现有所差异;- 但是从客户端业务角度,可以把它当作“我不再关心这个结果了”。
- destroy 是真正生命周期的终点
- 如果后续还要继续使用 URPC,建议重新走一遍
urpcStubCreate; - 不要销毁后继续复用同一个
stub引用。
- 如果后续还要继续使用 URPC,建议重新走一遍
五、考点速记版(考试/出题小抄)
- 能力名称: 使用 URPC 进行远程程序调用
- 设备支持: Phone / 2in1 / Tablet / Wearable,5.1.1(19) 起新增 TV
- 核心接口:
call(funcName, request, returnValue, config?): UrpcPromisecancel(callingId?: number | number[]): voiddestroy(): void
- 典型调用流程:
- 定义 Request / Response 类(基于
urpc.FlowbufElement<T>) - 配置
IpAndPort→UrpcConnectConfiguration→UrpcInitConfiguration urpc.urpcStubCreate(config, funcList)拿到urpcStub(Promise)stub.call("uploadFile", request, response, { priority: 0 })- 用
urpcPromise.promise.then / catch处理结果 - 需要时
stub.cancel(callingId)取消请求 - 结束时
stub.destroy()释放资源
- 定义 Request / Response 类(基于

浙公网安备 33010602011771号