👋 你好,欢迎来到我的博客!我是【菜鸟学鸿蒙】
   我是一名在路上的移动端开发者,正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来,也为了和更多同路人互相启发,我决定把探索 HarmonyOS 的过程都记录在这里。
  
  🛠️ 主要方向:ArkTS 语言基础、HarmonyOS 原生应用(Stage 模型、UIAbility/ServiceAbility)、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战,以及 Android → 鸿蒙的迁移踩坑与复盘。
  🧭 内容节奏:从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘,让每篇都有可落地的代码与方法论。
  💡 我相信:写作是把知识内化的过程,分享是让生态更繁荣的方式。
  
   如果你也想拥抱鸿蒙、热爱成长,欢迎关注我,一起交流进步!🚀

0. 先把目标说清楚:你到底想复用到什么程度?

我把复用分 4 档(别一上来就追求“最大复用”,那是给自己找罪受🙃):

  1. 协议与模型复用(强烈推荐):接口契约、数据模型、错误码、埋点事件定义
  2. 业务规则复用(推荐):价格计算、校验规则、排序/筛选、风控策略
  3. 数据层复用(视情况):缓存策略、离线策略、Repository 逻辑
  4. UI 复用(谨慎):鸿蒙 ArkUI vs Android(Compose/XML)差异很大,强行统一通常得不偿失

1) 代码复用策略:别复用“写法”,复用“事实”✅

1.1 第一优先级:接口契约与数据模型(最稳)

把“事实”写成一个 单一来源,两端生成代码或手写映射都行:

  • OpenAPI:定义 REST 接口 + 模型 → 两端生成客户端/模型
  • Protobuf/JSON Schema:定义模型/事件 → 两端生成/校验
  • 埋点事件表:统一事件名、字段、枚举值,避免两端各叫各的(最后数据平台哭给你看😭)

示例:Protobuf(或任何 schema)先定义一个 LoginResult

message LoginResult {
  string userId = 1;
  string token = 2;
  int64  expiresAt = 3;
}

两端各自生成/解析,然后进入各自的 Repository。你会发现:复用的不是代码,是“数据结构的真相”

1.2 第二优先级:核心业务算法/规则(建议用“可移植核心”)

如果你们确实有“同一套规则两端必须一致”(比如优惠计算/风控/离线索引)——建议用下面两种路线之一:

路线 A:用跨平台核心库(Rust/C++)

  • 优点:真正一份核心逻辑,两端绑定调用(Android JNI;鸿蒙 NAPI/Native 接入)
  • 缺点:工程复杂度上升、调试门槛更高

路线 B:用“规则 DSL/配置化”

  • 把规则做成 JSON/DSL,客户端只是解释执行
  • 优点:发布灵活,灰度方便
  • 缺点:解释器也要一致,性能要评估

我个人很现实😅:除非你们“必须强一致”,否则优先做 模型+规则对齐,不要一上来就上跨平台 Native 核心把团队拖进深坑。

1.3 第三优先级:网络/存储框架别强行复用

鸿蒙侧(ArkTS/ohpm/hvigor)和 Android(Gradle/Kotlin)生态不同。你复用网络层实现,往往会变成:
“为了省 5% 代码,多写 30% 适配胶水” 🤡
所以我建议:

  • 网络库、线程模型、存储实现:各端用各端成熟方案
  • 统一的:Repository 接口、错误模型、重试策略、缓存策略规范

2) UI 层差异处理:别统一 UI,统一“状态与意图”😤

2.1 共同点:都应该走“单向数据流”

不管 Android 是 Compose 还是传统 View,鸿蒙是 ArkUI,UI 层都建议这样:

UI(展示) ← State(状态) ← Reducer/UseCase(业务) ← Intent/Action(用户意图)

你统一的是:

  • State 的结构(页面需要哪些状态)
  • Intent 的集合(用户能做哪些动作)
  • Effect 的定义(导航、弹窗、Toast、埋点)

2.2 差异点:生命周期/导航/线程模型,各端自己兜

UI 层差异通常集中在:

  • 页面/Ability 生命周期 vs Activity/Fragment 生命周期
  • 路由栈(鸿蒙的 Ability/页面路由) vs Android Navigation
  • 权限弹窗机制、系统能力调用方式
  • 渲染与重组的“敏感点”(ArkUI 重组 vs Compose 重组)

策略:UI 层只做三件事:

  1. 把用户操作变成 Intent
  2. 订阅并渲染 State
  3. 处理 Effect(导航/弹窗/权限)

其他统统别塞 UI 里,不然两端都变“屎山 UI”😅

3) 业务层抽象:用 Clean Architecture/MVI 把两端“对齐但不绑死”✅

3.1 建议的分层(两端同一张图)

  • Domain(纯业务):UseCase、实体、业务规则、错误模型
  • Data(数据实现):Repository 实现、网络/缓存/数据库
  • Presentation(表现层):ViewModel/Store,产出 State/Effect
  • UI(平台层):ArkUI / Android UI 具体实现

关键:Domain 层要尽可能“无平台依赖”
这样你就算不做“一份代码复用”,也能做到“两端结构一致”,团队协作会顺很多🙂

3.2 一套跨端通用的“Intent/State”定义(示意)

你可以把“页面协议”当成跨端合同:

// 伪代码:概念示意(你可以用 TS 文档/Schema 来管理)
type LoginIntent =
  | { type: 'Submit'; username: string; password: string }
  | { type: 'OpenPrivacy' }
  | { type: 'RequestPermission' }

type LoginState = {
  loading: boolean
  errorMsg?: string
  userName: string
}

type LoginEffect =
  | { type: 'Toast'; message: string }
  | { type: 'Navigate'; target: 'Home' }

鸿蒙端 Store/VM 产出这些;Android 端 ViewModel 也产出这些。
你就实现两套“胶水 UI”,但业务语义完全一致,这就是“架构复用”的含金量😤

4) 工程组织方式:我推荐你用“单仓多端 + 共享规范层”📦

4.1 目录结构(长期不乱的那种)

repo/
  shared-spec/          # OpenAPI/Proto/埋点事件表/错误码/文档(强烈建议独立)
  shared-domain-doc/    # 领域模型与用例说明(不一定共享代码,但共享设计)
  harmony/              # 鸿蒙工程(ohpm/hvigor)
    entry/
    features/
    common-ui/
    common-data/
  android/              # Android 工程(Gradle)
    app/
    features/
    core-ui/
    core-data/
  tools/                # 代码生成、校验脚本、CI

4.2 依赖管理原则(别让“共享模块”变成垃圾场)

  • shared-spec:只放契约(schema、文档、生成脚本),不放平台实现
  • 端内 core-data:实现 Repository,但必须遵守 Domain 接口
  • Feature 模块:只依赖 Domain 接口,不直接依赖底层实现(避免“牵一发动全身”)

4.3 CI 的关键门禁(强烈建议)

  • schema 变更必须跑生成 + 编译两端(不然你今天改字段,明天两端都炸😅)
  • lint/格式化统一
  • 核心用例的契约测试(至少对错误码、关键字段做校验)

一个最实用的落地建议:先做到“语义一致”,再追求“代码一致”🙂

你会发现:

  • 只要 State/Intent/Effect + API 契约 + 错误模型统一,两端就不会“一个叫 A 一个叫 B”
  • 业务规则如果真的要求一致,再逐步引入跨平台核心库(别一上来上硬菜🥲)

📝 写在最后

如果你觉得这篇文章对你有帮助,或者有任何想法、建议,欢迎在评论区留言交流!你的每一个点赞 👍、收藏 ⭐、关注 ❤️,都是我持续更新的最大动力!

我是一个在代码世界里不断摸索的小码农,愿我们都能在成长的路上越走越远,越学越强!

感谢你的阅读,我们下篇文章再见~👋

✍️ 作者:某个被流“治愈”过的 移动端 老兵
📅 日期:2025-11-05
🧵 本文原创,转载请注明出处。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐