Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)

大家好,我是熊猫钓鱼!欢迎大家和我一起探讨技术。希望您能点赞关注,谢谢!

摘要

本文是「OpenHarmony 鸿蒙化三方库适配」系列的第 8 篇,也是「纯逻辑等价复刻」档的收官------在已交付 Decompose(组件化导航)、Essenty(生命周期/状态保持)、MVIKotlin(单向数据流)之后,补齐最底层的响应式原语 :arkivanov 开源的 Reaktive。Reaktive 提供 Observable/Single/Completable 等冷/热流类型,以及 map/filter/flatMap/subscribeOn/observeOn 操作符与 Scheduler 线程模型,是 Rx 思路的轻量实现,也是 MVIKotlin 的 Actor 异步副作用得以成立的底层支撑。

适配上,Reaktive 属于「等价复刻」路线,且连引擎层都不需要,只有「语义层 + 验收页」两层 ------系统里没有任何东西叫 Observable 或 Scheduler,全部用纯 ArkTS 还原。我们在 Reaktive.ets 中实现了 Disposable/CompositeDisposable(取消管理)、Scheduler(immediate/computation/io/main)、Emitter、Observable 及操作符、PublishSubject/BehaviorSubject(热流)、Single/Completable(一次性结果),不引入任何 @kit.*;并在 ReaktiveDemo.ets 用计时器演示 interval → map → filter → observeOn(main) → subscribe、Single 一次性结果、BehaviorSubject 订阅回放与 dispose 取消。全文还总结了 ArkTS 适配踩的 6 个坑(定时器句柄类型、泛型+函数类型数组、可选订阅回调、链式返回新 Observable、单线程调度语义、dispose 后不再发射),并与系列其它 7 个适配做了横向对比。

本适配基于 HarmonyOS SDK 6.0.0(20) + KMP&CMP 鸿蒙社区工具链 v1.1.0 (Kotlin 2.2.21 / CMP 1.9.2)开发,assembleHap 编译 BUILD SUCCESSFUL、零 ArkTS error ,纯逻辑零平台依赖,模拟器即可演示、无需任何权限或硬件。


目录

  • [一、为什么要适配 Reaktive](#一、为什么要适配 Reaktive)
    • 异步/流式数据的普遍需求;与 RxJava 同源、更轻更零依赖
    • 与 MVIKotlin 的关系:Actor 异步副作用的底层支撑
  • 二、路线取舍:等价复刻,且只有两层
    • 系列两条路线回顾(真接口真实现 / 等价复刻)
    • 为何 Reaktive 连引擎层都不需要(零系统 API、纯逻辑)
    • 为何不复用上游 Kotlin 源码
  • [三、语义层:把响应式契约画出来(不碰任何 @kit.*)](#三、语义层:把响应式契约画出来(不碰任何 @kit.*))
    • Disposable / CompositeDisposable:取消管理
    • Scheduler:线程调度模型(4 个静态实例)
    • Emitter:发射器
    • Observable + 操作符:map / filter / flatMap / subscribeOn / observeOn / interval
    • PublishSubject / BehaviorSubject:热流(订阅回放)
    • Single / Completable:一次性结果
  • 四、验收页:一个计时器讲清整条响应式链
    • interval + map + filter + observeOn(main) 冷流演示
    • Single 一次性结果
    • BehaviorSubject 回放
    • dispose 取消管理
    • 运行效果描述
  • 五、运行情况
    • 定时器句柄类型、泛型+函数类型数组、可选订阅回调、链式返回新 Observable、单线程调度语义、dispose 后不再发射
  • 六、和系列其它适配的对比
    • 七库路线 / 层级 / 平台依赖 / 模拟器可演示对比表
  • 七、版本与运行环境
    • 适配平台、工具链、IDE、编译验证结果
  • 八、小结与社区
    • 三层架构 + 等价复刻在纯逻辑库上的高效性;arkivanov 底座集齐
    • 社区引导语与 AtomCode 专属邀请链接、原创声明

正文

一、为什么要适配 Reaktive

写 KMP/CMP 应用,异步与流式数据处理无处不在:网络轮询、传感器采样、倒计时、事件总线......Reaktive 是 arkivanov 开源的 Kotlin 响应式库,提供 Observable/Single/Maybe/Completable 一串冷/热流类型,以及 map/filter/flatMap/subscribeOn/observeOn 等操作符和 Scheduler 线程模型。它和 RxJava 同源思路,但更轻、零依赖,是 MVIKotlin 的 Actor 异步副作用得以成立的底层支撑。

在 OpenHarmony 上,ArkTS 本身只提供 Promise 与 setTimeout/setInterval,没有「流式 + 可取消 + 可切换线程」的一等公民。我们的适配目标很明确:把 Reaktive 的响应式契约原样还原成 ArkTS,让上层业务零成本迁移 ,并且------因为它纯逻辑------模拟器就能完整演示,连真机都不用。

二、路线取舍:等价复刻,且只有两层

和 MVIKotlin 一样,Reaktive 属于「等价复刻」路线:系统里没有任何东西叫 Observable 或 Scheduler,所以连引擎层都不需要,只有「语义层 + 验收页」两层。

为什么不复用上游 Kotlin 源码?上游是 Kotlin,要在鸿蒙跑要么等 ohosArm64 目标、要么搬 Kotlin/Native 运行时,成本不可控;而 Reaktive 的契约本身就是几百行纯逻辑(发射、订阅、取消、调度),复刻比编译上游划算得多,还能随手丢进 Node 做离线单测。

本适配实现的核心类型:
![图1 Reaktive 响应式类型体系](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2ODAgNDQwIiB3aWR0aD0iMTAwJSIgZm9udC1mYW1pbHk9IidQaW5nRmFuZyBTQycsJ01pY3Jvc29mdCBZYUhlaScsc2Fucy1zZXJpZiIgcm9sZT0iaW1nIj4KICA8dGl0bGU+UmVha3RpdmUg5ZON5bqU5byP57G75Z6L5L2T57O777yIQXJrVFMg562J5Lu35aSN5Yi777yJPC90aXRsZT4KICA8ZGVzYz5EaXNwb3NhYmxlIOS4uuWPlua2iOeuoeeQhuWfuuexu++8m+WGt+a1gSBPYnNlcnZhYmxl44CB5LiA5qyh5oCnIFNpbmdsZS9Db21wbGV0YWJsZe+8m+eDrea1gSBQdWJsaXNoL0JlaGF2aW9yU3ViamVjdO+8m1NjaGVkdWxlciDmj5Dkvpvnur/nqIvosIPluqbjgII8L2Rlc2M+CiAgPGRlZnM+CiAgICA8bWFya2VyIGlkPSJhcnJvdyIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI4IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8tc3RhcnQtcmV2ZXJzZSI+CiAgICAgIDxwYXRoIGQ9Ik0yIDFMOCA1TDIgOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjb250ZXh0LXN0cm9rZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgPC9tYXJrZXI+CiAgPC9kZWZzPgogIDx0ZXh0IHg9IjM0MCIgeT0iMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMyNjIxNUMiPlJlYWt0aXZlIOWTjeW6lOW8j+exu+Wei+S9k+ezu++8iEFya1RTIOetieS7t+WkjeWIu++8iTwvdGV4dD4KICA8dGV4dCB4PSIzNDAiIHk9IjUwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEyIiBmaWxsPSIjNUY1RTVBIj7nuq/pgLvovpHvvIzkuI3lvJXlhaUgQGtpdC4qIMK3IOWGt+a1gSAvIOeDrea1gSAvIOS4gOasoeaAp+e7k+aenCAvIOWPlua2iCAvIOiwg+W6pjwvdGV4dD4KCiAgPHJlY3QgeD0iNjAiIHk9Ijc4IiB3aWR0aD0iNTYwIiBoZWlnaHQ9IjQ0IiByeD0iOCIgZmlsbD0iI0U2RjFGQiIgc3Ryb2tlPSIjMTg1RkE1IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjgwIiB5PSI5OCIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzBDNDQ3QyI+RGlzcG9zYWJsZSAvIENvbXBvc2l0ZURpc3Bvc2FibGU8L3RleHQ+CiAgPHRleHQgeD0iNjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9ImVuZCIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzVGNUU1QSI+5Y+W5raI566h55CG77yIaXNEaXNwb3NlZCAvIGRpc3Bvc2XvvIk8L3RleHQ+CiAgPGxpbmUgeDE9IjIwMCIgeTE9IjEyMiIgeDI9IjIwMCIgeTI9IjE0NiIgc3Ryb2tlPSIjMTg1RkE1IiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KICA8bGluZSB4MT0iMzQwIiB5MT0iMTIyIiB4Mj0iMzQwIiB5Mj0iMTQ2IiBzdHJva2U9IiMxODVGQTUiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93KSIvPgogIDxsaW5lIHgxPSI0ODAiIHkxPSIxMjIiIHgyPSI0ODAiIHkyPSIxNDYiIHN0cm9rZT0iIzE4NUZBNSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjYwIiB5PSIxNDgiIHdpZHRoPSIxNzAiIGhlaWdodD0iNzQiIHJ4PSI4IiBmaWxsPSIjRUFGM0RFIiBzdHJva2U9IiMzQjZEMTEiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iMTQ1IiB5PSIxNzIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTQiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMyNzUwMEEiPk9ic2VydmFibGUmbHQ7VCZndDs8L3RleHQ+CiAgPHRleHQgeD0iMTQ1IiB5PSIxOTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTEiIGZpbGw9IiM1RjVFNUEiPuWGt+a1ge+8muWPr+WkmuasoeWPkeWwhDwvdGV4dD4KICA8dGV4dCB4PSIxNDUiIHk9IjIxMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMSIgZmlsbD0iIzVGNUU1QSI+bWFwL2ZpbHRlci9mbGF0TWFw4oCmPC90ZXh0PgoKICA8cmVjdCB4PSIyNTUiIHk9IjE0OCIgd2lkdGg9IjE3MCIgaGVpZ2h0PSI3NCIgcng9IjgiIGZpbGw9IiNFRUVERkUiIHN0cm9rZT0iIzUzNEFCNyIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSIzNDAiIHk9IjE3MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzNDMzQ4OSI+U2luZ2xlJmx0O1QmZ3Q7PC90ZXh0PgogIDx0ZXh0IHg9IjM0MCIgeT0iMTk0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj7kuIDmrKHmgKfmiJDlip/lgLw8L3RleHQ+CiAgPHRleHQgeD0iMzQwIiB5PSIyMTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTEiIGZpbGw9IiM1RjVFNUEiPuWPryBtYXA8L3RleHQ+CgogIDxyZWN0IHg9IjQ1MCIgeT0iMTQ4IiB3aWR0aD0iMTcwIiBoZWlnaHQ9Ijc0IiByeD0iOCIgZmlsbD0iI0ZBRUVEQSIgc3Ryb2tlPSIjODU0RjBCIiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjUzNSIgeT0iMTcyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjNjMzODA2Ij5Db21wbGV0YWJsZTwvdGV4dD4KICA8dGV4dCB4PSI1MzUiIHk9IjE5NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMSIgZmlsbD0iIzVGNUU1QSI+5Y+q5YWz5b+D5a6M5oiQL+mUmeivrzwvdGV4dD4KICA8dGV4dCB4PSI1MzUiIHk9IjIxMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMSIgZmlsbD0iIzVGNUU1QSI+5peg6L+U5Zue5YC8PC90ZXh0PgoKICA8cmVjdCB4PSI2MCIgeT0iMjQ0IiB3aWR0aD0iNTYwIiBoZWlnaHQ9Ijc4IiByeD0iOCIgZmlsbD0iI0UxRjVFRSIgc3Ryb2tlPSIjMEY2RTU2IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjgwIiB5PSIyNjYiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMwODUwNDEiPlN1YmplY3TvvIjng63mtYHvvJrml6LmmK/op4Llr5/ogIXlj4jmmK/ooqvop4Llr5/ogIXvvIk8L3RleHQ+CiAgPHJlY3QgeD0iODAiIHk9IjI3OCIgd2lkdGg9IjI1MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iIzBGNkU1NiIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSIyMDUiIHk9IjMwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzA4NTA0MSI+UHVibGlzaFN1YmplY3TvvJrku4Xlub/mkq3lkI7nu608L3RleHQ+CiAgPHJlY3QgeD0iMzUwIiB5PSIyNzgiIHdpZHRoPSIyNTAiIGhlaWdodD0iMzQiIHJ4PSI2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiMwRjZFNTYiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iNDc1IiB5PSIzMDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMwODUwNDEiPkJlaGF2aW9yU3ViamVjdO+8muiuoumYheWNs+WbnuaUvjwvdGV4dD4KCiAgPHJlY3QgeD0iNjAiIHk9IjM0NCIgd2lkdGg9IjU2MCIgaGVpZ2h0PSI2NCIgcng9IjgiIGZpbGw9IiNGMUVGRTgiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSI4MCIgeT0iMzY2IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjMkMyQzJBIj5TY2hlZHVsZXLvvIjnur/nqIvosIPluqbmqKHlnovvvIk8L3RleHQ+CiAgPHRleHQgeD0iODAiIHk9IjM5MCIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzVGNUU1QSI+aW1tZWRpYXRlIMK3IGNvbXB1dGF0aW9uIMK3IGlvIMK3IG1haW7jgIAoc2V0VGltZW91dCDmqKHmi5/lvILmraXliIfnur/nqIspPC90ZXh0Pgo8L3N2Zz4K) `Disposable` / `CompositeDisposable`(取消管理)、`Scheduler`(immediate/computation/io/main)、`Emitter`、`Observable` + 操作符(`map`/`filter`/`flatMap`/`subscribeOn`/`observeOn`)、`PublishSubject` / `BehaviorSubject`(热流)、`Single` / `Completable`(一次性结果)。

开发过程如下:

编译通过:

三、语义层:把响应式契约画出来(不碰任何 @kit.*)

核心文件 Reaktive.ets 定义了一组角色,一一对应 Reaktive:

Disposable / CompositeDisposable ------ 取消管理

Disposable 是「可被取消的资源」契约(isDisposed / dispose)。CompositeDisposable 把多个 Disposable 合成一个:页面销毁时一次 dispose() 就能级联取消所有流,避免内存泄漏。这是响应式库和生命周期绑定的关键。

Scheduler ------ 线程调度模型

四个静态实例 immediate / computation / io / main。ArkTS 是单线程,我们用 setTimeout(task, 0) 模拟「切到另一个调度器执行」------schedule() 返回一个 TimeoutDisposable,取消即 clearTimeout。这样 subscribeOn / observeOn 的语义在单线程下依然成立,真机多线程场景把 setTimeout 换成 taskpool 即可平滑升级。
![图3 线程调度模型](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2ODAgNDQwIiB3aWR0aD0iMTAwJSIgZm9udC1mYW1pbHk9IidQaW5nRmFuZyBTQycsJ01pY3Jvc29mdCBZYUhlaScsc2Fucy1zZXJpZiIgcm9sZT0iaW1nIj4KICA8dGl0bGU+57q/56iL6LCD5bqm5qih5Z6L77yac3Vic2NyaWJlT24g5LiOIG9ic2VydmVPbjwvdGl0bGU+CiAgPGRlc2M+c3Vic2NyaWJlT24g5Yaz5a6a6K6i6ZiF5Zyo5ZOq5Liq6LCD5bqm5Zmo5Y+R6LW377yI5b2x5ZON5LiK5ri45omn6KGM57q/56iL77yJ77ybb2JzZXJ2ZU9uIOWGs+WumuWFtuWQjuS4i+a4uOWbnuiwg+WcqOWTquS4quiwg+W6puWZqOaJp+ihjOOAgjwvZGVzYz4KICA8ZGVmcz4KICAgIDxtYXJrZXIgaWQ9ImFycm93IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjgiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj4KICAgICAgPHBhdGggZD0iTTIgMUw4IDVMMiA5IiBmaWxsPSJub25lIiBzdHJva2U9ImNvbnRleHQtc3Ryb2tlIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPHRleHQgeD0iMzQwIiB5PSIyOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzI2MjE1QyI+57q/56iL6LCD5bqm5qih5Z6L77yac3Vic2NyaWJlT24g5LiOIG9ic2VydmVPbjwvdGV4dD4KICA8dGV4dCB4PSIzNDAiIHk9IjUwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEyIiBmaWxsPSIjNUY1RTVBIj5BcmtUUyDljZXnur/nqIvkuIvnlKggc2V0VGltZW91dCDmqKHmi5/lvILmraXliIfnur/nqIvvvIznnJ/mnLrlpJrnur/nqIvmlLnkuLogdGFza3Bvb2wg5Y2z5Y+vPC90ZXh0PgoKICA8cmVjdCB4PSI0MCIgeT0iMTAwIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjYwIiByeD0iOCIgZmlsbD0iI0VBRjNERSIgc3Ryb2tlPSIjM0I2RDExIiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjEyMCIgeT0iMTI2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjMjc1MDBBIj5PYnNlcnZhYmxlIOa6kDwvdGV4dD4KICA8dGV4dCB4PSIxMjAiIHk9IjE0NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMSIgZmlsbD0iIzVGNUU1QSI+aW50ZXJ2YWwgLyBqdXN0PC90ZXh0PgoKICA8cmVjdCB4PSIyNjAiIHk9IjEwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI2MCIgcng9IjgiIGZpbGw9IiNFNkYxRkIiIHN0cm9rZT0iIzE4NUZBNSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSIzNDAiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzBDNDQ3QyI+c3Vic2NyaWJlT24oaW8pPC90ZXh0PgogIDx0ZXh0IHg9IjM0MCIgeT0iMTQ2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj7orqLpmIXlj5Hotbfnur/nqIs8L3RleHQ+CgogIDxyZWN0IHg9IjQ4MCIgeT0iMTAwIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjYwIiByeD0iOCIgZmlsbD0iI0VFRURGRSIgc3Ryb2tlPSIjNTM0QUI3IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjU2MCIgeT0iMTI2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjM0MzNDg5Ij5vYnNlcnZlT24obWFpbik8L3RleHQ+CiAgPHRleHQgeD0iNTYwIiB5PSIxNDYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTEiIGZpbGw9IiM1RjVFNUEiPuS4i+a4uOWbnuiwg+e6v+eoizwvdGV4dD4KCiAgPGxpbmUgeDE9IjIwMCIgeTE9IjEzMCIgeDI9IjI1NiIgeTI9IjEzMCIgc3Ryb2tlPSIjNDQ0NDQxIiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KICA8bGluZSB4MT0iNDIwIiB5MT0iMTMwIiB4Mj0iNDc2IiB5Mj0iMTMwIiBzdHJva2U9IiM0NDQ0NDEiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93KSIvPgoKICA8cmVjdCB4PSI0ODAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI1NiIgcng9IjgiIGZpbGw9IiNGMUVGRTgiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSI1NjAiIHk9IjIyNCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzJDMkMyQSI+U3Vic2NyaWJlciAvIFVJPC90ZXh0PgogIDx0ZXh0IHg9IjU2MCIgeT0iMjQ0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj7kuLvnur/nqIvliLfmlrA8L3RleHQ+CiAgPGxpbmUgeDE9IjU2MCIgeTE9IjE2MCIgeDI9IjU2MCIgeTI9IjE5NiIgc3Ryb2tlPSIjNTM0QUI3IiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSw0IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93KSIvPgogIDx0ZXh0IHg9IjYwMCIgeT0iMTgyIiBmb250LXNpemU9IjExIiBmaWxsPSIjNTM0QUI3Ij7liIflm54gbWFpbjwvdGV4dD4KCiAgPHJlY3QgeD0iNDAiIHk9IjMwMCIgd2lkdGg9IjYwMCIgaGVpZ2h0PSIxMTAiIHJ4PSI4IiBmaWxsPSIjRjdGOEZBIiBzdHJva2U9IiNCNEIyQTkiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iNjAiIHk9IjMyNCIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzQ0NDQ0MSI+U2NoZWR1bGVyIOWbm+S4quWunuS+izwvdGV4dD4KICA8cmVjdCB4PSI2MCIgeT0iMzM2IiB3aWR0aD0iMTM1IiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjMTg1RkE1IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjEyNyIgeT0iMzYxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMEM0NDdDIj5pbW1lZGlhdGU8L3RleHQ+CiAgPHJlY3QgeD0iMjEwIiB5PSIzMzYiIHdpZHRoPSIxMzUiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiMxODVGQTUiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iMjc3IiB5PSIzNjEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMwQzQ0N0MiPmNvbXB1dGF0aW9uPC90ZXh0PgogIDxyZWN0IHg9IjM2MCIgeT0iMzM2IiB3aWR0aD0iMTM1IiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjMTg1RkE1IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjQyNyIgeT0iMzYxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMEM0NDdDIj5pbzwvdGV4dD4KICA8cmVjdCB4PSI1MTAiIHk9IjMzNiIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI0MCIgcng9IjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iIzE4NUZBNSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSI1NzAiIHk9IjM2MSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzBDNDQ3QyI+bWFpbjwvdGV4dD4KICA8dGV4dCB4PSI2MCIgeT0iMzk0IiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj5zdWJzY3JpYmVPbiDlvbHlk43kuIrmuLjmiafooYznur/nqIvvvJtvYnNlcnZlT24g5b2x5ZON5YW25ZCO5omA5pyJ5LiL5ri45Zue6LCD57q/56iL77yI5Y+v5aSa5qyh5YiH5o2i77yJPC90ZXh0Pgo8L3N2Zz4K)

Emitter<T> ------ 发射器

持有 onNext / onError / onComplete 三个回调,是「上游往下游推数据」的通道。

Observable<T> ------ 冷流 + 操作符

subscribe(onNext?, onError?, onComplete?) 是唯一的消费入口,返回一个 Disposable。操作符全部返回新 Observable(链式组合):

  • map(fn):变换每一项;
  • filter(pred):只放行符合条件的项;
  • flatMap(fn):把每一项展平成另一个 Observable,内部用 CompositeDisposable 收口所有内层订阅;
  • subscribeOn(scheduler) / observeOn(scheduler):分别决定「订阅发生在哪个调度器」和「下游回调在哪个调度器执行」。

Observable.interval(ms) 用 setInterval 周期性发射,是最直观的「无限冷流」演示源。
![图2 操作符管道](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2ODAgMzgwIiB3aWR0aD0iMTAwJSIgZm9udC1mYW1pbHk9IidQaW5nRmFuZyBTQycsJ01pY3Jvc29mdCBZYUhlaScsc2Fucy1zZXJpZiIgcm9sZT0iaW1nIj4KICA8dGl0bGU+5pON5L2c56ym566h6YGT77yaaW50ZXJ2YWwg4oaSIG1hcCDihpIgZmlsdGVyIOKGkiBvYnNlcnZlT24g4oaSIHN1YnNjcmliZTwvdGl0bGU+CiAgPGRlc2M+5Ya35rWB5rqQIGludGVydmFsIOavjyAxcyDlj5HlsITvvIznu48gbWFwKCoyKeOAgWZpbHRlciglND09MCnjgIFvYnNlcnZlT24obWFpbikg5ZCO55SxIHN1YnNjcmliZSDmtojotLnlubbliLfmlrAgVUnjgII8L2Rlc2M+CiAgPGRlZnM+CiAgICA8bWFya2VyIGlkPSJhcnJvdyIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI4IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8tc3RhcnQtcmV2ZXJzZSI+CiAgICAgIDxwYXRoIGQ9Ik0yIDFMOCA1TDIgOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjb250ZXh0LXN0cm9rZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgPC9tYXJrZXI+CiAgPC9kZWZzPgogIDx0ZXh0IHg9IjM0MCIgeT0iMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMyNjIxNUMiPuaTjeS9nOespueuoemBk++8mmludGVydmFsIOKGkiBtYXAg4oaSIGZpbHRlciDihpIgb2JzZXJ2ZU9uIOKGkiBzdWJzY3JpYmU8L3RleHQ+CiAgPHRleHQgeD0iMzQwIiB5PSI1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzVGNUU1QSI+5q+P5Liq5pON5L2c56ym6L+U5Zue5pawIE9ic2VydmFibGXvvIzpk77lvI/nu4TlkIjvvJvkuIvmuLjlnKggc2NoZWR1bGVyIOS4iuaJp+ihjDwvdGV4dD4KCiAgPHJlY3QgeD0iNDAiIHk9IjEyMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI2NCIgcng9IjgiIGZpbGw9IiNFQUYzREUiIHN0cm9rZT0iIzNCNkQxMSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSI5NSIgeT0iMTQ2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjMjc1MDBBIj5pbnRlcnZhbDwvdGV4dD4KICA8dGV4dCB4PSI5NSIgeT0iMTY2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj7mr48gMXMg5Y+R5bCEPC90ZXh0PgoKICA8cmVjdCB4PSIxOTAiIHk9IjEyMCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgcng9IjgiIGZpbGw9IiNFNkYxRkIiIHN0cm9rZT0iIzE4NUZBNSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSIyNDAiIHk9IjE0NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzBDNDQ3QyI+bWFwPC90ZXh0PgogIDx0ZXh0IHg9IjI0MCIgeT0iMTY2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj5uIOKGkiBuw5cyPC90ZXh0PgoKICA8cmVjdCB4PSIzMzAiIHk9IjEyMCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgcng9IjgiIGZpbGw9IiNGQUVFREEiIHN0cm9rZT0iIzg1NEYwQiIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8dGV4dCB4PSIzODAiIHk9IjE0NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iIzYzMzgwNiI+ZmlsdGVyPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTY2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjExIiBmaWxsPSIjNUY1RTVBIj4lND09MDwvdGV4dD4KCiAgPHJlY3QgeD0iNDcwIiB5PSIxMjAiIHdpZHRoPSIxMjAiIGhlaWdodD0iNjQiIHJ4PSI4IiBmaWxsPSIjRUVFREZFIiBzdHJva2U9IiM1MzRBQjciIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iNTMwIiB5PSIxNDYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMzQzM0ODkiPm9ic2VydmVPbjwvdGV4dD4KICA8dGV4dCB4PSI1MzAiIHk9IjE2NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMSIgZmlsbD0iIzVGNUU1QSI+5YiH5YiwIG1haW48L3RleHQ+CgogIDxyZWN0IHg9IjYxMCIgeT0iMTIwIiB3aWR0aD0iNDAiIGhlaWdodD0iNjQiIHJ4PSI4IiBmaWxsPSIjRjFFRkU4IiBzdHJva2U9IiM0NDQ0NDEiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iNjMwIiB5PSIxNDYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMyQzJDMkEiPlVJPC90ZXh0PgogIDx0ZXh0IHg9IjYzMCIgeT0iMTY2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEwIiBmaWxsPSIjNUY1RTVBIj7liLfmlrA8L3RleHQ+CgogIDxsaW5lIHgxPSIxNTAiIHkxPSIxNTIiIHgyPSIxODYiIHkyPSIxNTIiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CiAgPGxpbmUgeDE9IjI5MCIgeTE9IjE1MiIgeDI9IjMyNiIgeTI9IjE1MiIgc3Ryb2tlPSIjNDQ0NDQxIiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KICA8bGluZSB4MT0iNDMwIiB5MT0iMTUyIiB4Mj0iNDY2IiB5Mj0iMTUyIiBzdHJva2U9IiM0NDQ0NDEiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93KSIvPgogIDxsaW5lIHgxPSI1OTAiIHkxPSIxNTIiIHgyPSI2MDYiIHkyPSIxNTIiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjQwIiB5PSIyNDAiIHdpZHRoPSI2MDAiIGhlaWdodD0iMTAwIiByeD0iOCIgZmlsbD0iI0Y3RjhGQSIgc3Ryb2tlPSIjQjRCMkE5IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDx0ZXh0IHg9IjYwIiB5PSIyNjIiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiM0NDQ0NDEiPuWPkeWwhOW6j+WIl++8iOavjyAxc++8iTwvdGV4dD4KICA8dGV4dCB4PSI2MCIgeT0iMjg2IiBmb250LXNpemU9IjEyIiBmaWxsPSIjNUY1RTVBIj4wLDEsMiwzLDQsNSw2LDcsOCDigKY8L3RleHQ+CiAgPHRleHQgeD0iNjAiIHk9IjMwOCIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNCNkQxMSI+bWFww5cyIOKGkiAwLDIsNCw2LDgsMTAsMTIsMTQsMTYg4oCmPC90ZXh0PgogIDx0ZXh0IHg9IjYwIiB5PSIzMzAiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiM4NTRGMEIiPmZpbHRlciAlND09MCDihpIgMCw0LDgsMTIsMTYg4oCmIOKGkiBVSSDmiZPljbAgdGljaz0wLDQsOCwxMjwvdGV4dD4KPC9zdmc+Cg==)

PublishSubject / BehaviorSubject ------ 热流

既是观察者又是被观察者:onNext 就广播给当前订阅者;BehaviorSubject 额外「订阅即回放当前值」,对应状态持有型总线。

Single / Completable ------ 一次性结果

Single 发射恰好一次成功值(可 map);Completable 只关心完成/错误。对应「一次异步调用」语义。

四、验收页:一个计时器讲清整条响应式链

ReaktiveDemo.ets 用三个按钮把冷流、热流、一次性结果全部点亮:

  • 开始 interval :Observable.interval(1000).map(n => n*2).filter(n => n%4===0).observeOn(Scheduler.main).subscribe(...)。你会看到日志每 1s 打印一次 tick = 0, 4, 8, 12...(0 的两倍是 0、1 的两倍 2 被 filter 掉、2 的两倍 4 通过......),并且 UI 在主线程刷新。
  • 执行 Single :Single.just(42).map(v => v+8).subscribe(...),日志立刻打印 single result = 50,演示「一次异步计算结果」。
  • BehaviorSubject 回放 :进页即订阅,日志先打印 subject → 初始值,证明订阅即拿到当前值。
  • 停止 / dispose :cd.dispose() 后 interval 立刻停发,日志打印「所有流已停止」------证明取消管理生效。

跑起来:进页自动打印 BehaviorSubject 回放;点「开始 interval」看每秒计数;点「Single」看一次性结果;点「停止」看流被取消。整条响应式闭环一目了然。
![图4 验收页运行时时序](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2ODAgNjAwIiB3aWR0aD0iMTAwJSIgZm9udC1mYW1pbHk9IidQaW5nRmFuZyBTQycsJ01pY3Jvc29mdCBZYUhlaScsc2Fucy1zZXJpZiIgcm9sZT0iaW1nIj4KICA8dGl0bGU+UmVha3RpdmVEZW1vIOi/kOihjOaXtua1geeoi++8iOW4pue8luWPt+mXreeOr++8iTwvdGl0bGU+CiAgPGRlc2M+6L+b6aG1IEJlaGF2aW9yU3ViamVjdCDlm57mlL4g4oaSIOeCuSBpbnRlcnZhbCDlkK/liqjlhrfmtYEg4oaSIOavjyAxcyDnu48gbWFwL2ZpbHRlci9vYnNlcnZlT24g5YiwIFVJIOKGkiDngrnlgZzmraIgZGlzcG9zZSDlj5bmtojjgII8L2Rlc2M+CiAgPGRlZnM+CiAgICA8bWFya2VyIGlkPSJhcnJvdyIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI4IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8tc3RhcnQtcmV2ZXJzZSI+CiAgICAgIDxwYXRoIGQ9Ik0yIDFMOCA1TDIgOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjb250ZXh0LXN0cm9rZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgPC9tYXJrZXI+CiAgPC9kZWZzPgogIDx0ZXh0IHg9IjM0MCIgeT0iMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI1MDAiIGZpbGw9IiMyNjIxNUMiPlJlYWt0aXZlRGVtbyDov5DooYzml7bmtYHnqIvvvIjluKbnvJblj7fpl63njq/vvIk8L3RleHQ+CiAgPHRleHQgeD0iMzQwIiB5PSI1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzVGNUU1QSI+5Ya35rWB5Y+v6KKrIGRpc3Bvc2Ug5Y+W5raIIMK3IEJlaGF2aW9yU3ViamVjdCDorqLpmIXljbPlm57mlL4gwrcg5Y2V5qyh57uT5p6c55SoIFNpbmdsZTwvdGV4dD4KCiAgPHJlY3QgeD0iMTAwIiB5PSI3NiIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSI0NCIgcng9IjgiIGZpbGw9IiNFMUY1RUUiIHN0cm9rZT0iIzBGNkU1NiIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KICA8Y2lyY2xlIGN4PSIxMjQiIGN5PSI5OCIgcj0iMTMiIGZpbGw9IiMwRjZFNTYiLz4KICA8dGV4dCB4PSIxMjQiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjRkZGRkZGIj4xPC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iOTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMwODUwNDEiPui/m+mhtSBhYm91dFRvQXBwZWFyIOKGkiBCZWhhdmlvclN1YmplY3Qg6K6i6ZiF5Y2z5Zue5pS+44CM5Yid5aeL5YC844CNPC90ZXh0PgogIDxsaW5lIHgxPSIzNDAiIHkxPSIxMjAiIHgyPSIzNDAiIHkyPSIxMzQiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjEwMCIgeT0iMTM2IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjQ0IiByeD0iOCIgZmlsbD0iI0VBRjNERSIgc3Ryb2tlPSIjM0I2RDExIiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDxjaXJjbGUgY3g9IjEyNCIgY3k9IjE1OCIgcj0iMTMiIGZpbGw9IiMzQjZEMTEiLz4KICA8dGV4dCB4PSIxMjQiIHk9IjE1OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iI0ZGRkZGRiI+MjwvdGV4dD4KICA8dGV4dCB4PSIxNTAiIHk9IjE1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzI3NTAwQSI+54K544CM5byA5aeLIGludGVydmFs44CN4oaSIGNkLmFkZChpbnRlcnZhbC5tYXAuZmlsdGVyLm9ic2VydmVPbi5zdWJzY3JpYmUpPC90ZXh0PgogIDxsaW5lIHgxPSIzNDAiIHkxPSIxODAiIHgyPSIzNDAiIHkyPSIxOTQiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjEwMCIgeT0iMTk2IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjQ0IiByeD0iOCIgZmlsbD0iI0U2RjFGQiIgc3Ryb2tlPSIjMTg1RkE1IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDxjaXJjbGUgY3g9IjEyNCIgY3k9IjIxOCIgcj0iMTMiIGZpbGw9IiMxODVGQTUiLz4KICA8dGV4dCB4PSIxMjQiIHk9IjIxOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iI0ZGRkZGRiI+MzwvdGV4dD4KICA8dGV4dCB4PSIxNTAiIHk9IjIxOCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzBDNDQ3QyI+5q+PIDFz77yaaW50ZXJ2YWwg5Y+R5bCEIG48L3RleHQ+CiAgPGxpbmUgeDE9IjM0MCIgeTE9IjI0MCIgeDI9IjM0MCIgeTI9IjI1NCIgc3Ryb2tlPSIjNDQ0NDQxIiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KCiAgPHJlY3QgeD0iMTAwIiB5PSIyNTYiIHdpZHRoPSI0ODAiIGhlaWdodD0iNDQiIHJ4PSI4IiBmaWxsPSIjRTZGMUZCIiBzdHJva2U9IiMxODVGQTUiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPGNpcmNsZSBjeD0iMTI0IiBjeT0iMjc4IiByPSIxMyIgZmlsbD0iIzE4NUZBNSIvPgogIDx0ZXh0IHg9IjEyNCIgeT0iMjc4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjRkZGRkZGIj40PC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iMjc4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjMEM0NDdDIj5tYXDvvJpuIOKGkiBuw5cyPC90ZXh0PgogIDxsaW5lIHgxPSIzNDAiIHkxPSIzMDAiIHgyPSIzNDAiIHkyPSIzMTQiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjEwMCIgeT0iMzE2IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjQ0IiByeD0iOCIgZmlsbD0iI0ZBRUVEQSIgc3Ryb2tlPSIjODU0RjBCIiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDxjaXJjbGUgY3g9IjEyNCIgY3k9IjMzOCIgcj0iMTMiIGZpbGw9IiM4NTRGMEIiLz4KICA8dGV4dCB4PSIxMjQiIHk9IjMzOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iI0ZGRkZGRiI+NTwvdGV4dD4KICA8dGV4dCB4PSIxNTAiIHk9IjMzOCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzYzMzgwNiI+ZmlsdGVy77ya5LuF5pS+6KGMIG4lND09MO+8iDAsNCw4LDEy4oCm77yJPC90ZXh0PgogIDxsaW5lIHgxPSIzNDAiIHkxPSIzNjAiIHgyPSIzNDAiIHkyPSIzNzQiIHN0cm9rZT0iIzQ0NDQ0MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYXJyb3cpIi8+CgogIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjQ0IiByeD0iOCIgZmlsbD0iI0VFRURGRSIgc3Ryb2tlPSIjNTM0QUI3IiBzdHJva2Utd2lkdGg9IjAuNSIvPgogIDxjaXJjbGUgY3g9IjEyNCIgY3k9IjM5OCIgcj0iMTMiIGZpbGw9IiM1MzRBQjciLz4KICA8dGV4dCB4PSIxMjQiIHk9IjM5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjUwMCIgZmlsbD0iI0ZGRkZGRiI+NjwvdGV4dD4KICA8dGV4dCB4PSIxNTAiIHk9IjM5OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzNDMzQ4OSI+b2JzZXJ2ZU9uKG1haW4pIOKGkiDnu5PmnpzmtL7lj5HliLDkuLvnur/nqIs8L3RleHQ+CiAgPGxpbmUgeDE9IjM0MCIgeTE9IjQyMCIgeDI9IjM0MCIgeTI9IjQzNCIgc3Ryb2tlPSIjNDQ0NDQxIiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KCiAgPHJlY3QgeD0iMTAwIiB5PSI0MzYiIHdpZHRoPSI0ODAiIGhlaWdodD0iNDQiIHJ4PSI4IiBmaWxsPSIjRjFFRkU4IiBzdHJva2U9IiM0NDQ0NDEiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPGNpcmNsZSBjeD0iMTI0IiBjeT0iNDU4IiByPSIxMyIgZmlsbD0iIzQ0NDQ0MSIvPgogIDx0ZXh0IHg9IjEyNCIgeT0iNDU4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjRkZGRkZGIj43PC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iNDU4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjMkMyQzJBIj5VSe+8mnRpY2sg5pu05pawICsg5pel5b+X5omT5Y2wIHRpY2s9MCw0LDgsMTLigKY8L3RleHQ+CiAgPGxpbmUgeDE9IjM0MCIgeTE9IjQ4MCIgeDI9IjM0MCIgeTI9IjQ5NCIgc3Ryb2tlPSIjNDQ0NDQxIiBzdHJva2Utd2lkdGg9IjEuNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvdykiLz4KCiAgPHJlY3QgeD0iMTAwIiB5PSI0OTYiIHdpZHRoPSI0ODAiIGhlaWdodD0iNDQiIHJ4PSI4IiBmaWxsPSIjRkFFQ0U3IiBzdHJva2U9IiM5OTNDMUQiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPGNpcmNsZSBjeD0iMTI0IiBjeT0iNTE4IiByPSIxMyIgZmlsbD0iIzk5M0MxRCIvPgogIDx0ZXh0IHg9IjEyNCIgeT0iNTE4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNTAwIiBmaWxsPSIjRkZGRkZGIj44PC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iNTE4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNzEyQjEzIj7ngrnjgIzlgZzmraLjgI3ihpIgY2QuZGlzcG9zZSgpIOKGkiBjbGVhckludGVydmFsIOWBnOatouWPkeWwhDwvdGV4dD4KCiAgPHJlY3QgeD0iMTAwIiB5PSI1NTYiIHdpZHRoPSI0ODAiIGhlaWdodD0iMzIiIHJ4PSI4IiBmaWxsPSIjRjFFRkU4IiBzdHJva2U9IiM0NDQ0NDEiIHN0cm9rZS13aWR0aD0iMC41Ii8+CiAgPHRleHQgeD0iMzQwIiB5PSI1NzciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTEiIGZpbGw9IiMyQzJDMkEiPmRpc3Bvc2Ug5ZCO5LiN5YaN5omT5Y2w77ya5Y+W5raI566h55CG55Sf5pWI77yM5rWB6KKr57qn6IGU5Y+W5raIPC90ZXh0Pgo8L3N2Zz4K)

五、运行情况

执行相关效果如下:

ArkTS 适配踩的坑:

  1. 定时器句柄类型 :setTimeout / setInterval 返回 number,但 TS 声明有时是联合类型;用 as number 收口,并把句柄存进 Disposable,clearTimeout / clearInterval 才能精确取消。
  2. 泛型 + 函数类型数组 :PublishSubject 内部用 ((v: T) => void)[] 存订阅者。ArkTS 支持泛型类与函数类型数组,但字段必须初始化(= []),否则编译报状态可变性错误。
  3. 可选订阅回调 :subscribe 的 onNext?/onError?/onComplete? 用 ?? 兜底成空实现,避免上层不传时调用崩溃;onError 兜底默认 throw,保留「未处理错误即抛出」的 Rx 语义。
  4. 链式返回新 Observable :每个操作符都 new Observable(...) 包一层,订阅时层层透传 emitter。注意 flatMap 的内层订阅必须收进 CompositeDisposable,否则内层流泄漏、无法随外层一起取消。
  5. 单线程下的调度器语义 :Scheduler.schedule 用 setTimeout(0) 模拟异步切线程。subscribeOn 决定「订阅动作在哪个调度器发起」,observeOn 决定「下游回调在哪个调度器执行」------单线程下两者都退化为「下次事件循环执行」,但代码结构与多线程真机一致,便于升级。
  6. dispose 后不再发射 :interval 的 Disposable 在 clearInterval 后不再触发;BehaviorSubject 在 done 后置位后 onNext 直接丢弃,避免向已销毁页面写 @State。

六、和系列其它适配的对比

库 路线 层级 平台依赖 模拟器可演示
Decompose 等价复刻 语义+验收 无 ✅(逻辑可离线测)
Essenty 等价复刻 语义+验收 无 ✅
Ktor 真接口真实现 语义+引擎+验收 @ohos.net.http ✅(需网络权限)
Notifier 真接口真实现 语义+引擎+验收 @kit.NotificationKit ✅(需通知授权)
kable 真接口真实现 语义+引擎+验收 @kit.ConnectivityKit ⚠️(BLE 需真机,模拟器用模拟演示)
MVIKotlin 等价复刻 语义+验收 无 ✅(零权限零硬件)
Reaktive 等价复刻 语义+验收 无 ✅(零权限零硬件,纯逻辑)

纯逻辑类(Decompose / Essenty / MVIKotlin / Reaktive)是最「好实现」的一档;Reaktive 因为连副作用都只是 setTimeout,是其中演示最顺、依赖最干净的之一。

七、版本与运行环境

  • 适配目标平台:HarmonyOS SDK 6.0.0(20)(API 20)
  • 工具链:KMP&CMP 鸿蒙社区工具链 v1.1.0(Kotlin 2.2.21 / CMP 1.9.2)
  • IDE:DevEco Studio 26.0.0 Release
  • 编译验证:assembleHap BUILD SUCCESSFUL,零 ArkTS error

八、小结与社区

Reaktive 的适配再次验证了「三层架构 + 等价复刻」在纯逻辑类 KMP 库上的高效:几百行 ArkTS 把响应式原语(冷流/热流/一次性结果/取消/调度)完整还原,零平台依赖、模拟器即跑、可离线单测。配合 Decompose / Essenty / MVIKotlin,arkivanov 的「状态管理 + 响应式」底座在 OpenHarmony 上正式集齐。

欢迎加入 KMP&CMP 鸿蒙社区:https://atomgit.com/CPF-KMP-CMP

AtomCode 专属邀请链接:

https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwatomgit1\&sourcead=dmzntgwatomgiths

相关推荐
姜楠聊AI转型1 小时前
AI 编程安全合规怎么落地?三大风险 + 四道防线(数据脱敏 / 漏洞左移 / 审计 / 权限路由)
ai编程·vibe coding·ai coding·coding agent
李游Leo4 小时前
HarmonyOS 7 + Spatial Recon Kit-C++:3DGS 高斯参数的非有限值隔离与可渲染性门禁【鸿蒙心迹】
开发语言·c++·3d·harmonyos
熊猫钓鱼>_>4 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 MVIKotlin 实现单向数据流适配
华为·ai编程·鸿蒙·openharmony·适配·数据流·mvkotlin
Alice-YUE4 小时前
前端 × AI:从 Cursor 到 Transformer,一份完整认知路径
前端·人工智能·transformer·ai编程·前端开发·cursor
deepseek234 小时前
Kolibri 拆解:计算像 3.5B、显存要 78GB 的德国主权模型,把合规做进六个架构决策
开源·大模型·moe·aiagent·ai架构
传奇开心果编程4 小时前
【ArkUI进阶练中学】第12课:应用架构演进与遗留系统迁移
学习·ui·华为·harmonyos
FanetheDivine5 小时前
学习Agent开发 10.延迟工具 deferred tools
agent·ai编程