Kuikly 扩展原生 API 的完整流程,保持原始代码完整性,并通过多端对比(Kuikly/Android/iOS/鸿蒙)和参数传递、回调通信的详细说明:
1. Kuikly 侧 Module 定义与调用
(1)定义 Module 类
kotlin
class MyLogModule : Module() {
override fun moduleName(): String = "KRMyLogModule" // 必须与原生侧一致
// 无返回值调用
fun log(content: String) {
toNative(
keepCallbackAlive = false,
methodName = "log", // 原生侧方法名
param = content, // 传递字符串参数
callback = null, // 无回调
syncCall = false // 异步调用
)
}
// 异步回调
fun logWithCallback(content: String, callbackFn: CallbackFn) {
toNative(
keepCallbackAlive = false,
methodName = "logWithCallback",
param = content,
callback = callbackFn, // 原生侧通过此回调返回结果
syncCall = false
)
}
// 同步调用(阻塞当前线程)
fun syncLog(content: String): String {
return toNative(
keepCallbackAlive = false,
methodName = "syncLog",
param = content,
callback = null,
syncCall = true // 同步调用,直接返回结果
).toString()
}
}
(2)注册 Module
kotlin
internal class TestPage : Pager() {
override fun createExternalModules(): Map<String, Module>? {
return mapOf("KRMyLogModule" to MyLogModule()) // Key 必须与 moduleName() 一致
}
override fun created() {
val logModule = acquireModule<MyLogModule>("KRMyLogModule")
logModule.log("Hello") // 异步无回调
logModule.logWithCallback("World") { result ->
// 原生侧回调的 JSON 结果
println("Callback result: $result")
}
val syncResult = logModule.syncLog("Sync") // 同步阻塞
}
}
2. 原生侧实现对比
Android 侧
kotlin
class KRMyLogModule : KuiklyRenderBaseModule() {
// 统一入口,根据 methodName 分发调用
override fun call(method: String, params: String?, callback: KuiklyRenderCallback?): Any? {
return when (method) {
"log" -> log(params ?: "")
"logWithCallback" -> logWithCallback(params ?: "", callback)
"syncLog" -> syncLog(params ?: "")
else -> super.call(method, params, callback)
}
}
private fun log(content: String) {
Log.d("Kuikly", content) // 简单打印
}
private fun logWithCallback(content: String, callback: KuiklyRenderCallback?) {
Log.d("Kuikly", content)
callback?.invoke(mapOf("result" to "OK")) // 回调结果给 Kuikly
}
private fun syncLog(content: String): String {
Log.d("Kuikly", content)
return "Success" // 同步返回字符串
}
}
// 注册 Module(在 KuiklyRenderViewDelegatorDelegate 实现类中)
override fun registerExternalModule(export: IKuiklyRenderExport) {
export.moduleExport("KRMyLogModule") { KRMyLogModule() } // Key 必须一致
}
iOS 侧
less
// KRMyLogModule.h
@interface KRMyLogModule : KRBaseModule
@end
// KRMyLogModule.m
@implementation KRMyLogModule
// 方法名必须与 Kuikly 侧 methodName 一致
- (void)log:(NSDictionary *)args {
NSString *content = args[HR_PARAM_KEY]; // 参数键固定
NSLog(@"Kuikly Log: %@", content);
}
- (void)logWithCallback:(NSDictionary *)args {
NSString *content = args[HR_PARAM_KEY];
NSLog(@"Kuikly Log: %@", content);
KuiklyRenderCallback callback = args[KR_CALLBACK_KEY]; // 回调键固定
callback(@{@"result": @"OK"}); // 回调结果
}
- (id)syncLog:(NSDictionary *)args {
NSString *content = args[HR_PARAM_KEY];
NSLog(@"Kuikly Log: %@", content);
return @"Success"; // 同步返回
}
@end
鸿蒙侧(ArkTS)
typescript
export class KRMyLogModule extends KuiklyRenderBaseModule {
static readonly MODULE_NAME = "KRMyLogModule";
syncMode(): boolean { return true; } // 允许同步调用
call(method: string, params: KRAny, callback: KuiklyRenderCallback | null): KRAny {
switch (method) {
case 'log':
console.log(`Kuikly Log: ${params as string}`);
break;
case 'logWithCallback':
console.log(`Kuikly Log: ${params as string}`);
callback?.({ result: "OK" }); // 回调结果
break;
case 'syncLog':
console.log(`Kuikly Log: ${params as string}`);
return "Success"; // 同步返回
}
return null;
}
}
// 注册 Module(在 IKuiklyViewDelegate 实现类中)
getCustomRenderModuleCreatorRegisterMap(): Map<string, KRRenderModuleExportCreator> {
const map = new Map<string, KRRenderModuleExportCreator>();
map.set(KRMyLogModule.MODULE_NAME, () => new KRMyLogModule());
return map;
}
3. 参数传递与回调通信
参数类型支持
Kuikly 侧 | 原生侧接收方式 |
---|---|
String |
Android/iOS/鸿蒙均通过 params 字段获取 |
Int /Double |
自动转换为原生数字类型 |
Array |
转换为原生数组(如 NSArray /List ) |
JSON 对象 |
需序列化为字符串传递,原生侧解析 |
回调通信
-
异步回调:
Kuikly 侧通过
CallbackFn
接收原生侧的callback.invoke(result)
或callback(result)
。 -
同步返回:
原生侧直接返回
String
或基本类型(如 Android 的Any?
、iOS 的id
)。
线程模型
调用方式 | Kuikly 线程 | 原生侧线程 |
---|---|---|
异步调用 | 非 UI 线程 | Android/iOS 主线程 |
同步调用 | 阻塞当前线程 | 原生侧子线程(Android) |
4. 关键注意事项
-
命名一致性
- Kuikly 的
moduleName()
、注册时的 Key、原生类名必须完全一致。 - 方法名(如
log
)需在 Kuikly 和原生侧严格匹配。
- Kuikly 的
-
参数键固定
- iOS 使用
HR_PARAM_KEY
和KR_CALLBACK_KEY
获取参数和回调对象。
- iOS 使用
-
JSON 处理
- 复杂数据需在 Kuikly 侧序列化为
String
,原生侧反序列化(如JSON.parse
)。
- 复杂数据需在 Kuikly 侧序列化为
-
同步调用限制
- 鸿蒙需显式启用
syncMode(): boolean = true
。
- 鸿蒙需显式启用
通过以上对比和完整代码展示,可以清晰看到 Kuikly 扩展原生 API 的多端协作机制,包括模块定义、注册、参数传递和回调通信的全流程。