鸿蒙、iOS、安卓:三个平行宇宙里的开发日常

引言

我写过Swift(IOS),写过Kotlin(Android),这两年,我也开始写ArkTS(HarmonyOS)

而这次,就来分享一下三个系统开发的不一样~

它们看起来像三兄弟,其实是三个平行宇宙。

infographic compare-binary-horizontal-simple-fold
data
  title 三个平台,两种活法
  items
    - label 鸿蒙的甜
      children
        - label 一套 ArkUI 通吃多端
          desc 手机、平板、PC、车机共用同一套声明式框架
        - label 系统能力接口统一
          desc 权限、网络、界面都从同一套 Kit 里出来
        - label 工程链路闭环
          desc DevEco Studio 与方舟编译器同源,少吵构建的架
    - label 鸿蒙的苦
      children
        - label 三方库密度低
          desc 很多轮子得自己造,或者等别人移植
        - label 严格模式的门槛
          desc 存量 JS 库不能直接搬,要按 ArkTS 规则重写
        - label 海外市场缺席
          desc 用户主要在国外的话,现在不该选它

先看看同一种功能的实现方法

ArkTS(鸿蒙)

@Entry
@Component
struct CounterPage {
  @State count: number = 0;

  build() {
    Column({ space: 12 }) {
      Text(`当前计数:${this.count}`)
        .fontSize(20)
        .fontColor('#182431')
      Button('点我 +1')
        .onClick(() => {
          this.count += 1;   // 改状态,UI 自己会跟上
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

SwiftUI(iOS)

struct CounterView: View {
    @State private var count = 0

    var body: some View {
        VStack(spacing: 12) {
            Text("当前计数:\(count)")
                .font(.system(size: 20))
            Button("点我 +1") {
                count += 1
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Jetpack Compose(安卓)

@Composable
fun CounterScreen() {
    var count by remember { mutableStateOf(0) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "当前计数:$count", fontSize = 20.sp)
        Button(onClick = { count += 1 }) {
            Text("点我 +1")
        }
    }
}

三份代码的骨架几乎一模一样:声明式 UI + 状态驱动。但实际上还是有区别的:

flowchart TB
    subgraph IOS["iOS · 精装修房间"]
        I1["Swift 语言<br/>ARC 内存管理"] --> I2["SwiftUI / UIKit<br/>苹果自家框架"]
        I2 --> I3["Xcode + 模拟器"]
        I3 --> I4["App Store<br/>唯一分发口"]
    end
    subgraph ANDROID["安卓 · 自由市场"]
        A1["Kotlin / Java<br/>ART 虚拟机 + GC"] --> A2["Compose / View<br/>厂商可定制"]
        A2 --> A3["Android Studio<br/>真机碎片化严重"]
        A3 --> A4["Google Play / 各厂商商店"]
    end
    subgraph HARMONY["鸿蒙 · 一栈通全部终端"]
        H1["ArkTS(UI)<br/>+ C/C++(Native)<br/>+ 仓颉(孵化中)"] --> H2["ArkUI 声明式框架<br/>系统统一提供"]
        H2 --> H3["DevEco Studio<br/>一套工程多端产物"]
        H3 --> H4["应用市场 + 元服务<br/>手机/平板/PC/车机/穿戴"]
    end

这张图里最关键的是中间那一层。iOS 和安卓的框架层,是「一家公司/一个社区做出来的 UI 工具包」;鸿蒙的 ArkUI 是「操作系统的一部分」,是系统直接提供给全场景设备的统一渲染与交互层。我认为这是「多端部署」不同于响应式布局的一个关键区别。

ArkTS 不是 TypeScript

在阅读鸿蒙开发文档的时候,我发现有很多 TypeScript 的语法在ArkTS中被严格限制。

// 这些在 .ts 里都合法,在 .ets 里全部报错
let data: any = getData();              // ❌ arkts-no-any-unknown
const obj = { name: 'koharu', age: 15 }; // ❌ arkts-no-untyped-obj-literals
const key = 'name';
console.log(obj[key]);                   // ❌ 禁止动态属性访问
eval('1 + 1');                           // ❌ 禁止 eval
delete obj.name;                         // ❌ 禁止 delete

把 ArkTS 的严格模式摊成一张表,方便对照:

特性TypeScriptArkTS为什么禁
any / unknown允许禁止编译器要能静态确定每个值的类型,才能提前布局内存
as 类型断言允许禁止断言等于「相信我」,而 AOT 编译器不能靠信仰工作
结构类型允许名义类型结构相同的两个类不能互赋值,必须显式继承
对象字面量任意写必须有显式类型无类型字面量无法在编译期分配固定内存布局
obj[key] 动态访问允许禁止属性访问必须在编译期解析成固定偏移
eval / with / delete允许禁止它们让「编译期确定一切」这个前提直接失效

通过阅读鸿蒙系统的架构介绍,就能知道原因,这样做其实是为了 AOT 编译。

ArkTS 代码会被编译成方舟字节码,再提前编译成本地机器码。要让这件事成立,编译器必须在打包时就知道「这个对象有几个字段、每个字段什么类型、占多少字节」。any 让这件事不可能,delete 让这件事在运行时失效,obj[key] 让属性访问从「查表」变成「算偏移」。

flowchart LR
    A["ArkTS 源码<br/>.ets"] --> B["ArkCompiler<br/>静态类型检查"]
    B --> C["方舟字节码<br/>.abc"]
    C --> D["AOT 提前编译"]
    D --> E["本地机器码<br/>启动即执行"]
    F["TypeScript 源码"] -.-> G["JIT 边跑边编译<br/>热点才优化"]

对比一下:V8 跑 JS 靠 JIT,热点代码才被优化成机器码,冷启动时边解释边编译;方舟的路线是打包阶段就把优化做完。代价是写代码时必须「像个静态语言」,收益是应用启动更快、内存更可预测。

这其实带来了一个很实在的优点:因为限制多,ArkTS 的报错来得特别早。IDE 在写错的那一刻就知道类型不对。而不是等你点下运行、真机上转三秒圈之后给你一个 undefined is not a function。

状态管理差异,从「钉钉子」到「挂画」

命令式 UI 时代,改一个数字要在三个地方手动同步:数据模型、视图对象、局部刷新调用。漏一个就是「界面没更新」的经典 bug。

声明式把这件事翻了过来:你只描述「数据是什么」和「数据长什么样」,同步由框架负责。三个平台的做法各有风格:

平台状态声明传值方式心智模型
鸿蒙 ArkUI@State / @Prop / @Link / @Provide / @Consume装饰器标注父子流向「给数据贴上标签,框架按标签决定谁能改」
iOS SwiftUI@State / @Binding / @Observable属性包装器「值语义 + 单向数据流」
安卓 Composeremember { mutableStateOf() }参数传递 + ViewModel「函数式重组,状态提升到调用方」

ArkUI 这套装饰器将可修改的权限安排的很好。

@Component
struct ParentView {
  @State total: number = 0;          // 自己拥有,自己可改
  @Provide('theme') theme: string = 'light';  // 向下广播,后代都能取

  build() {
    Column() {
      ChildView({ count: this.total })   // 单向传入,子组件只读
      DeepChild()                        // 深处组件用 @Consume 直接取主题
    }
  }
}

@Component
struct ChildView {
  @Prop count: number;                // 父给的值,本地可改但不回传
  @Link total: number;                // 与父双向绑定,改了父也变
  build() {
    Button(`加一(${this.count})`)
      .onClick(() => { this.total += 1; })
  }
}

@State 是自留地,@Prop 是单向水管,@Link 是双向水管,@Provide/@Consume 是跨层级广播(类似 React 的 Context,但语法上更重一点)。这套设计比 Compose 的「状态提升」啰嗦,但比 React 时代手动 useContext + useReducer 省心。它把「数据流向」写进了类型系统里,这是 ArkUI 我觉得做得相当漂亮的一个地方。

一个坑:为什么是 struct 而不是 class

如果你有 React 或 Vue 的底子,第一眼看到 ArkUI 一定会卡在这个字上:为什么组件用 struct 声明,而不是 class?

因为 ArkUI 的组件会被反复重新执行。状态一变,框架重新跑一遍 build(),把新描述和旧描述做 diff,只更新变化的那部分。这个模型要求组件本身是「无身份的、可以随时重建的」——用 struct(值语义)表达这件事,比用 class(引用语义)贴切得多。class 意味着你可能有实例字段、有 this 上的可变状态、有生命周期,而这些东西在「重新执行 build」的模型里全是隐患。

另外。ArkUI 的状态管理有 V1 和 V2 两套模型。V1 是 @State / @Prop / @Link 那套装饰器;V2 引入了 @ComponentV2 + @Local / @Param / @Event / @ObservedV2 / @Trace,主要是为了解决 V1 在深层嵌套对象上的观测粒度问题。重点来了:

两套模型不能混用在同一个组件里。

V2 组件里不能出现 V1 装饰器,反过来也一样。虽说是避免两套观测机制互相打架而做的硬性隔离,但确实为开发带来不少小麻烦 /(ㄒoㄒ)/~~

鸿蒙真正的独特之处:一次开发,多端部署

前面说的都是「三种方言」,到这里才是鸿蒙独有的一句话。

它的官方完整表述是十六个字:一次开发、多端部署、可分可合、自由流转。前八个字是界面适配,后八个字是分布式能力。

界面适配这一半,是三层机制叠出来的:

infographic sequence-pyramid-simple
data
  title 一次开发多端部署的三层机制
  items
    - label 交互归一
    - label 自适应布局
    - label 断点与栅格
theme
  palette
    - #8b5cf6
    - #3b82f6
    - #06b6d4

机制一:断点 + 栅格,让「一份布局」自己变形

ArkUI 定义了一套标准断点。单位是 vp(虚拟像素,密度无关)而不是 px:

断点宽度范围典型设备
sm[0, 320) vp小屏手机、手表
md[320, 520) vp大屏手机
lg[520, 840) vp平板竖屏
xl[840, +∞) vp平板横屏、折叠屏展开、PC

有了断点,栅格布局就能「一份代码、四种长相」:

@Entry
@Component
struct GalleryPage {
  @State items: number[] = [1, 2, 3, 4, 5, 6];

  build() {
    GridRow({
      columns: { sm: 4, md: 8, lg: 12 },      // 总列数随断点变
      gutter: { x: 12, y: 12 }
    }) {
      ForEach(this.items, (item: number) => {
        GridCol({ span: { sm: 2, md: 4, lg: 3 } }) {  // 每个卡片占几列也随断点变
          Column() {
            Text(`卡片 ${item}`).fontSize(16)
          }
          .height(96)
          .width('100%')
          .backgroundColor('#F1F3F5')
          .borderRadius(12)
        }
      })
    }
    .width('100%')
    .padding(16)
  }
}

手机上一行两列,平板上一行四列。代码里没有一个 if (isTablet)。

要用运行时更细的控制,还能订阅断点变化:

import { mediaQuery } from '@kit.ArkUI';

aboutToAppear() {
  const rule = mediaQuery.matchMediaSync('(840vp<=width)');
  rule.on('change', (result: mediaQuery.MediaQueryResult) => {
    this.isWide = result.matches;   // 折叠屏展开的瞬间就能收到
  });
}

机制二:自适应布局,让容器自己分配空间

光有断点还不够——折叠屏用户会一边看视频一边拖窗口,宽度是连续变化的,不是离散跳变。所以 ArkUI 还有一层自适应能力:RelativeContainer 做相对约束,layoutWeight 让子元素按权重瓜分剩余空间,Flex 做流式换行。这一层不依赖断点,是连续响应。

Row() {
  if (this.isWide) {
    Column() { Text('侧边栏') }.width(240)
  }
  Column() { Text('主内容') }
    .layoutWeight(1)      // 剩下的空间全给它,不用算具体宽度
}
.width('100%')

机制三:交互归一,一次点击适配五种输入

这层最容易被忽略。

多端意味着同一个按钮会被手指点(手机)、被鼠标点(PC)、被遥控器选中(智慧屏)、被旋钮转(手表)、被语音唤起(车机)。如果每种输入都要单独写事件,那「一次开发」就是空话。

ArkUI 的做法是在组件层面把输入抽象掉:你写 .onClick(),系统负责把触屏 tap、鼠标 click、键盘 Enter、遥控器确认键统一映射过来。你写 .onHover(),PC 上才有鼠标悬停,手机上不触发也不报错。业务代码不需要知道用户在用什么设备。

那「可分可合」是什么

上面三层解决的是「一份 UI 适配多个屏幕」。鸿蒙还多走了一步:一个应用可以拆成多个可独立运行的能力单元。

听起来抽象,看 module.json5 就懂了:

{
  "module": {
    "name": "entry",
    // 这个模块能在哪些设备上安装——打包时会按设备类型分别产出
    "deviceTypes": ["phone", "tablet", "2in1", "wearable", "car"],
    "abilities": [
      {
        "name": "EntryAbility",
        "exported": true,
        "skills": [{ "entities": ["entity.system.home"], "actions": ["action.system.home"] }]
      }
    ]
  }
}

deviceTypes 里那个 2in1 指的是 PC 形态设备。同一份工程在打包时会按设备类型分别产出安装包,应用市场上不同设备看到的是各自的版本。这就是「一次开发」在工程层面的落地方式。

更进一步是「元服务」——把应用里的一部分能力拆出来,做成免安装、卡片化、可以被系统智能推荐的原子化服务。这跟 iOS 的 App Clips 有点像,区别在于鸿蒙把它当成了系统级的一等公民:服务卡片可以直接放在桌面,可以被小艺建议调度,可以跨设备调用。

但是依然存在缺点

说了这么多好话,必须补一句实话。

「一次开发多端部署」省掉的是重复编写业务逻辑的成本,没有省掉为每种设备设计交互的成本。手机的底部标签栏搬到 PC 上就是灾难,平板的双栏布局在手表上根本放不下。断点和栅格给你的是工具,不是答案——你依然得想清楚「这个功能在手表上应该长什么样」,只不过想清楚之后不用重写一遍。

官方文档里那句「一次开发,多端部署」后面其实还有半句潜台词:一次设计,多端思考。

生态现状

这里聊聊鸿蒙生态,鸿蒙到现在已经7年了,我一直都在关注,这一路走来确实非常不容易,到本文截稿已有8000万设备,但生态上仍然任重而道远。

infographic compare-swot
data
  title 鸿蒙生态 SWOT
  items
    - label 优势 (Strengths)
      children
        - label 多设备统一框架
        - label 系统能力接口一致
        - label 国内产业推力真实
    - label 劣势 (Weaknesses)
      children
        - label 三方库密度低
        - label 文档质量参差
        - label 模拟器体验一般
    - label 机会 (Opportunities)
      children
        - label 全场景设备增量
        - label 元服务新形态
        - label 仓颉语言生态
    - label 威胁 (Threats)
      children
        - label 海外市场缺位
        - label 开发者迁移成本
        - label 存量应用适配周期

优点

第一,系统能力的调用被统一了。 这是我最喜欢的一点。在安卓上做一个「长按弹出菜单 + 震动反馈 + 跨应用分享」,你可能要对接三套厂商 API,还要处理各家返回码不一致。鸿蒙上这些能力都从同一套 Kit 里出:@kit.ArkUI 管界面,@kit.AbilityKit 管能力,@kit.NetworkKit 管网络。导入路径统一,文档同一套,返回值风格一致。少了一半的搜索时间。

第二,权限模型是「最小授权」导向的。 鸿蒙把权限分成了 system_grant(装的时候就给)和 user_grant(运行时问用户)两类,并且对敏感权限支持「单次授权」这种粒度。iOS 在这条路上走得很远(隐私清单、App Tracking Transparency),鸿蒙追得很快,安卓相对最松。对用户是好事,对开发者是「必须把授权流程想清楚」的额外工作量。

第三,开发工具是一套闭环。 DevEco Studio、方舟编译器、模拟器、性能分析器、上架流程,全部来自同一家。少了「Android Studio 版本和 Gradle 版本和 Kotlin 版本互相打架」这类玄学调试时间。不用花整个下午跟构建系统吵架,这件事的价值被严重低估了。

第四,国内市场有实打实的推力。 鸿蒙原生应用的适配在国内已经是政务、金融、出行、社交各行业的既定动作,这意味着需求侧是真实的,不是只有极客在自娱自乐。

缺点

第一,三方库生态还薄。 这是最硬的一条。iOS 有 CocoaPods/SPM 十几年攒下来的库,安卓有 Maven Central 和 JitPack,你想找个「带圆角的图片压缩库」大概率有人写过。鸿蒙这边,很多时候答案是「自己写一个」或者「找找有没有人移植过」。

第二,ArkTS 的严格模式让存量 JS 库没法直接搬。 那些依赖动态特性、any、原型链魔改的 npm 包,在 ArkTS 里基本要重写。官方提供了三方库移植的路径,但移植本身是要人力和时间的工作。

第三,文档质量参差。 主流 API 的文档写得很细,连参数取值范围的边界情况都列了;但偏门一点的场景,经常出现「文档只写了一半,剩下的一半要靠社区帖子或读源码」。我在处理一个跨设备数据同步的问题时,最后是靠读一个两年老的论坛回复解决的。

第四,模拟器还不算好用。 冷启动慢,某些系统能力在模拟器上表现和真机不一致——这点上 Xcode 的模拟器依然是行业天花板,安卓的模拟器靠真机兜底,鸿蒙目前只能老老实实插真机测。

第五,海外市场几乎为零。 如果你的用户主要在国外,鸿蒙现在不是一个值得投入的目标平台,这是地理和生态的现实,跟技术好坏无关。

简单对比

维度iOS安卓鸿蒙
语言与框架成熟度极高高中(迭代很快)
三方库丰富度极高极高低
多设备形态统一中(各设备独立 SDK)中(Wear/TV 分开)高(一套 ArkUI 通吃)
开发工具体验极佳中好
分发渠道单一(App Store)分散较集中(应用市场)
海外市场全球全球基本没有
学习曲线(有前端基础)中中低(但严格模式要适应)

鸿蒙现在的短板全在「生态密度」上,长处全在「系统统一性」上。 生态密度是可以靠时间和钱堆出来的,系统统一性则是架构决定的、很难后天补的。所以我对它的长期判断偏乐观,对它的短期体验保持清醒。

仓颉:为什么鸿蒙还要再造一门语言

ArkTS 已经能写 UI 了,C/C++ 能写 Native 层,那为什么华为还要花五年时间从零造一门语言?

先给时间线(都是公开信息):仓颉的研发大约从 2019 年开始;2025 年 7 月 31 日,华为在 AtomGit 上正式开源了仓颉的编译器、运行时和标准库;此后仓颉发布了首个 LTS 版本 1.0.0,从「内部语言」变成了可以真正拿来写东西的语言。

它和 ArkTS 的分工

这个问题在官方《鸿蒙编程语言白皮书》里说得很清楚:ArkTS 负责声明式 UI,仓颉负责业务逻辑与系统级能力,两者可以互操作。虽然到截稿时,我依然觉得互操作的开发文档写的奇烂无比。

仓颉ArkTS
文件后缀.cj.ets
定位通用编程语言声明式 UI 语言
范式多范式(OOP / FP / 命令式)以声明式 UI 为核心
并发模型用户态线程 + 并发对象单线程事件循环
内存管理自动 GC(全并发 GC)自动 GC
类型系统静态强类型 + 类型推断静态强类型(TS 子集)

介绍下「用户态线程」。

ArkTS 的并发模型是单线程事件循环——UI 在主线跑,耗时任务丢到 Worker 或 TaskPool 里,跨线程通信要序列化。这是移动端的标准做法(iOS 的 main thread、安卓的主线程 + 协程都是这个思路),但它有个天然限制:并发粒度是被系统框死的。

仓颉直接给了轻量级用户态线程(类似 Go 的 goroutine),再加一层「并发对象」库。它的目标是让你写并发代码时不需要手动加锁:

// 并发对象:多线程访问时由运行时保证安全,不用自己写锁
public class Counter {
    private var value: Int64 = 0

    public func increase(): Unit {
        synchronized(this) {
            value += 1
        }
    }

    public func get(): Int64 {
        synchronized(this) {
            return value
        }
    }
}

再加上仓颉本来就有代数数据类型和模式匹配,写业务逻辑的表达力明显强于 ArkTS:

enum NetworkResult {
    | Success(String)
    | Failure(Int64, String)
}

func handle(result: NetworkResult): String {
    match (result) {
        case Success(body) => "拿到数据:${body}"
        case Failure(code, msg) where code >= 500 => "服务器打盹了(${code}):${msg}"
        case Failure(code, msg) => "请求失败(${code}):${msg}"
    }
}

这段代码如果翻译成 ArkTS,你得写一个联合类型 + 一层 if 判断 + 手动保证所有分支都处理到。仓颉的 match 在编译期就能告诉你「你漏了一个分支」——类型系统帮你干掉了整整一类 bug。

仓颉还支持 extend,能给已有类型加方法,这点和 Swift 的 extension 很像:

extend String {
    public func shout(): String {
        return this + "!!!"
    }
}

main() {
    println("仓颉".shout())   // 仓颉!!!
}

我对仓颉的看法

仓颉现在还是「值得学,但不急着用」的状态。

值得学,是因为它的设计很干净。代数数据类型、模式匹配、值类型、用户态线程、extend——这些特性没有一个是新发明,但组合在一起就构成了一门「知道自己在干什么」的语言。它不像某些为了赶风口仓促推出的语言那样塞满半成品特性。

不急着用,是因为工具链和生态还在长。IDE 支持、调试体验、三方库、社区问答量,都处在早期阶段。现在拿它做正式项目,你大概率会成为那个「帮别人踩坑的人」——如果你享受这件事,那正好;如果你只想按时交付,再等一两个版本会更舒服。

LeetCode 中国目前已经支持使用 Cangjie 答题了,对于第一个“中国造”编程语言,我也在积极学习,用仓颉写算法题和练手小工具。

所以一门鸿蒙应用,将来大概会这样分层:

infographic hierarchy-structure
data
  title 未来鸿蒙应用的代码分层
  desc 三层各司其职,用互操作粘起来
  items
    - label 界面层
      children
        - label ArkTS + ArkUI
        - label 声明式状态管理
        - label 断点与栅格适配
    - label 业务层
      children
        - label 仓颉
          children
            - label 并发对象
            - label 模式匹配
            - label 值类型
    - label 系统层
      children
        - label C / C++
        - label Native API

未来的看法

一、鸿蒙的差异化会越来越集中在「多设备」上,而不是「单设备」

单设备的 UI 框架,三个平台已经卷到没有明显差距了:声明式、状态驱动、热重载、可视化预览,大家都有。真正拉开距离的是「手机、平板、PC、车机、手表能不能算一台设备」。

flowchart LR
    A["现在的鸿蒙<br/>一套代码 + 断点适配<br/>多产物打包"] --> B["正在发生的<br/>自由流转<br/>任务跨设备接力"]
    B --> C["目标形态<br/>设备边界消失<br/>算力与屏幕按需调度"]

「自由流转」这个词现在还有点理想主义色彩——真机体验里偶尔会有延迟、会有状态同步不完整。但方向是明确的:当你的手机、平板、车机、手表共享同一套系统底座时,「把任务从这台设备挪到那台设备」应该像拖动一个窗口一样自然。这是 iOS 和安卓在架构上做不到的事——它们的设备之间隔着不同的系统版本、不同的框架、不同的账号体系。作为新生的系统,这是非常好的优势。

二、AI 会从「一个功能」变成「一层能力」

以前做 AI 功能,是应用里加一个「智能助手」入口,接一个 API,用户点进去问问题。鸿蒙的路线是把 AI 能力下沉到系统层,让应用通过系统接口拿到智能能力,而不是每个应用都自己接一遍模型。

对开发者的影响很实际:你不需要再自己实现一套意图识别,也不需要为了调用系统级智能去猜接口。当然这也意味着新的适配工作——多了一层系统 API 要学。

三、仓颉和 ArkTS 会长期共存,而不是谁吃掉谁

声明式 UI 和系统级编程的诉求是冲突的。

UI 代码需要的是「快速迭代、热重载、语法糖多、写起来短」;系统级代码需要的是「确定性、零开销抽象、精确的内存与并发控制」。硬要用一门语言同时满足这两边,结果通常是两边都不舒服。Swift 和 SwiftUI 的关系、Kotlin 和 Compose 的关系,都已经证明了这一点:同一个生态里,UI 层和逻辑层可以有不同的语言风格。

sequenceDiagram
    participant U as 用户操作
    participant A as ArkTS / ArkUI
    participant C as 仓颉逻辑层
    participant N as C/C++ Native
    U->>A: 点击「开始导入」
    A->>C: 调用仓颉函数(互操作)
    C->>C: 并发解析 + 模式匹配分发
    C->>N: 调用底层编解码
    N-->>C: 返回结果
    C-->>A: 通过状态回传
    A-->>U: 界面自动刷新

所以我猜未来的鸿蒙应用长这样:ArkTS 写界面和交互,仓颉写核心业务与并发,C/C++ 留给真正需要抠性能的角落。三层各司其职,用互操作粘起来。

总结

iOS 在追求「同一个体验的极致打磨」,安卓在追求「最大程度的开放自由」,而鸿蒙在追一个更冒险的命题:能不能让一套代码自然地活在所有屏幕尺寸和形态上,并且让这些设备像一台设备一样协作。

它现在做得还不够好——三方库太少,文档偶尔坑人,模拟器让人想砸键盘。但它的短板几乎全是「时间能解决的」,而它的长处是「架构决定的」。这两件事的性质完全不同,前者会变好,后者不会变差。

© 2026 ChinoKoyuki