HarmonyOS 多端实战:把手机 UI 搬上大屏后,我翻车了 📅 2026/7/15 3:42:15 HarmonyOS 一次开发、多端部署实战Phone、Pad、PC、Watch 到底该共享什么最开始做 Nameo 多端适配时我不是“差点”把 Phone 页面直接搬到大屏——我真的搬了而且它还真的跑起来了。然后尴尬也跟着跑来了。Phone 那一小块布局安静地待在屏幕正中间左右两边空得十分讲礼貌谁也不挨着谁。到了设置页内容在目标窗口里看起来大约只占六成剩下的地方仿佛在提醒我这是一块很大的屏幕而你只带来了一颗很小的心。那一刻我脑子里只有一个问题如果用户把应用装到 Pad 或 PC 上看到的只是“手机版远距离观赏模式”那他安装大屏版本的意义是什么“一次开发多端部署”最容易制造的误会就是把“一次开发”听成“一张页面到处拉伸”。如果 CtrlC 真能解决多端开发架构师可能早就转行卖键盘了。这篇不做 ArkUI API 大全。我想拿 Nameo 的 Phone、Pad、PC、Watch 实际拆分讲清楚五件事设备职责怎么定、代码共享到哪一层、什么时候共用 HAP、什么时候独立拆包以及“能构建”和“真机跑过”到底差多少。一、“一次开发”的“一”不是一张 UIHarmonyOS 官方把“一多”拆成工程组织、功能兼容和界面适配几个层次。翻译成项目里的大白话就是工程尽量是一套数据模型、存储、网络和业务能力尽量共享到了产品体验层允许每种设备诚实地不一样。所以 Nameo 当前并不是“四个端就复制四个工程”也不是“一张 UI 按屏幕比例缩放”。它的真实拓扑是4 种产品体验3 个产品 HAP Phone HAP ── phone tablet PC HAP ── 2in1 Wearable ── wearable根据真实配置脱敏简化后三个入口的差异就是// Phone entry deviceTypes: [phone, tablet] // PC entry deviceTypes: [2in1] // Wearable entry deviceTypes: [wearable]Phone 和 Pad 共用一个 HAP但不共用一张页面PC 和 Watch 因为任务、交互方式、产品能力差异更大使用独立产品入口。如果你刚从 Java/Vue 转过来可以先这样理解HAP 是应用的部署包单元HAR 是静态共享包这里说的 feature是按业务能力拆出的模块Shell 则是一端页面的导航与布局外壳。共享的是“会做什么”产品层决定“在这台设备上怎么做才不别扭”。图里画的是主干不是一条必须逐层穿过的流水线products会按需依赖features和commonfeatures也会依赖common。二、我不是先分屏幕而是先分四种用户时刻多端规划如果从“手机多少寸、平板多少寸”开始很容易最后只剩一张响应式尺寸表。Nameo 先问的是用户为什么在这一刻拿起这台设备端用户时刻主要职责坚决不直接搬过去的东西Phone信息刚出现随手记一下语音、拍照、文件、分享采集即时问答和轻量待办PC 多栏管理、长时间批量编辑Pad坐下来阅读、整理或开会列表详情、会议工作区、知识整理和筛选只把 Phone 页面横向拉宽PC办公桌面批量处理多工作区、文件采集、会议、知识与待办重操作手机底部导航和一层层返回Watch抬腕几秒钟确认或补记摘要、待办、闪卡、知识速览、短输入长文编辑、复杂表单和多层导航这些职责不是先画一张漂亮表格再往项目里套而是从大屏空旷、导航上下文丢失、PC 专属工作流和 Watch 圆屏限制等实际问题倒推出来的。Phone 解决“别让信息跑掉”Pad 解决“上下文别总被新页面顶走”PC 解决“我现在要坐下来认真干活”Watch 解决“抬腕看一眼、点一下、说一句”。让手表编辑五千字会议纪要不叫“一次开发多端部署”叫对手腕实施职场霸凌。三、Phone 和 Pad 为什么共用 HAP却不共用 ShellNameo 的 Phone entry 同时声明了phone和tablet。窗口创建或尺寸变化后工程会把像素换算成 vp再根据 600vp、840vp 两个项目断点写入布局状态Window size ↓ BreakpointSystem ↓ compact / regular / expanded ↓ Phone Shell / PadAdaptiveShell这里有一个特别容易写错的判断断点判断的是当前窗口不是设备身份证。我关心的不是“你是不是折叠屏”而是“你现在展开到了什么窗口形态”。按窗口断点的设计宽折叠、双折叠、三折叠在不同展开状态下可能进入不同布局窄窗口继续走 Phone 形态达到regular/expanded后信息结构才切成 Pad 工作台。这里说的是布局策略不代表当前版本已经验收了所有折叠型号。脱敏后的核心分支其实很短constmodeupdateBreakpoint(windowWidthVp)if(modecompact){PhoneShell()}else{PadAdaptiveShell()}这也是我们没有急着再拆一个独立 Tablet HAP 的重要原因。未来达到regular/expanded窗口的折叠形态本身就需要复用 Pad 布局。如果 Phone、Tablet 过早分成两套产品后面同一套适配要维护两遍同一 bundle 下再塞一个 Tablet entry还会带来安装、共存和测试成本。算完这笔账我决定先不拆而不是为了目录看起来更“多端”就多造一个包。但“共用 HAP”绝不等于“Pad 是大号 Phone”。Phone 上打开知识卡可以进入独立详情页Pad 上打开同一张卡左侧列表应该保留只更新右侧详情。Phone 上页面跳转是合理导航Pad 上如果每点一次都把工作区整个顶走大屏就只剩“屏幕大迷路也更远”。四、设置页把我教育了大屏不是把 width 改成 100%第一次直接搬 Phone 设置页时最刺眼的问题就是中央内容太小、两边太空。但修复它也不是把每一行强行拉满整块屏幕。如果“AI 模式”开关从左边横跨到右边信息之间的关联反而会变弱。Nameo 后来的 Pad 设置不再沿用手机的长列表而是单独做了设置工作区账号中心、声纹、系统设置、关于页各自进入工作区登录资料与知识统计可以组成双栏设置项按成对的两列重新组织内容区还设置最大宽度避免在超宽窗口里无限拉长。注意这里的关键不是某个固定百分比。设置页“约占六成”只是我当时看到的现象不是 HarmonyOS 规范。真正可复用的方法是窄窗口接近全宽保证可用 中宽窗口开始重排单栏变双栏 大窗口限制内容宽度给结构留白而不是给空白留白留白本身没有罪。没有信息结构的留白才会让用户觉得“这应用只是被放大了”。五、Nameo 为什么最终让 PC 独立拆包看到这里可能有人会问既然 Phone/Pad 可以共用PC 为什么不继续共用对 Nameo 来说决定因素不是多了一种设备而是 PC 的任务、窗口、交互和功能演进已经与移动端明显分叉。Nameo 的 PC 不只是多一个侧栏。它有独立的桌面工作台和自由窗口处理AI 通话收起后是能在窗口内拖动、带边界约束的浮条会议有列表/详情和录制控制/实时转写的双栏结构文件采集要承接系统选择、待处理文件和批量入库。这些都不是在 Phone 页面外面包一层if (isPC)就能体面解决的。我一开始也舍不得拆。毕竟代码都写了能共用一行是一行。但当产品层的判断越来越像春运售票窗口——Phone 走左边、Tablet 走右边、2in1 请上二楼——所谓复用就已经变成大家挤在同一间屋子里互相打扰。所以 PC 使用独立产品 HAP但这不意味着全部重写。PC 的页面、路由、窗口和交互独立待办、知识、会议和认证等领域能力仍然依赖共享模块。一句话概括PC 拆的是产品体验不是把业务底座也复制一份。六、feature 到底拆多细我的标准不是“看起来高级”Nameo 的工程边界可以简化成三层。注意这里不是一条必须逐层经过的单行流水线产品层会同时依赖 feature 和 commonfeature 也会依赖 common。products ├─ phonePhone 页面 Pad adaptive 工作台 ├─ pc桌面窗口、导航和 PC 交互 └─ wearable圆屏、表冠和轻动作 ├────→ featurestodo / knowledge / chat / me / meeting └────→ common模型、数据库、KV、网络、认证、底层服务 features ─→ commoncommon不是“暂时不知道放哪儿”的代码收容所features也不是为了目录好看而切得越碎越好。我现在判断拆分力度会连续问三个问题这段代码在不同端解决的是不是同一个业务问题它们变化的原因是不是相同抽出来以后产品层会不会反而塞满端类型判断待办的读取、完成状态持久化、知识卡更新可以共享Pad 的筛选工作区、PC 的分组列表、Watch 的紧凑字段投影不该硬共享。变化原因相同的代码才值得放到一起不是长得像就必须住一间房。七、同一份数据为什么仍会在不同端出问题多端架构图画完以后最容易产生一种错觉既然 ViewModel 和 Repository 共用了四端状态就会自动整齐得像军训方阵。现实当然没有这么配合。同一条待办在领域层有相同语义读取、勾选、持久化、同步。但到了产品层Pad 会投影成待处理/已处理与类型筛选PC 会按普通、紧急、逾期重新分组Watch 只保留标题、待办文本和完成按钮等紧凑字段。共享 ViewModel 更新不等于这些端侧二次数组一定自动刷新。上一篇《Java 程序员第一次看 ArkTS像老乡但口音有点重》里详细复盘过的“PC 待办勾选后数量变了、列表不动”本质上就是这一类问题数据已经变了界面仍然持有旧快照。最后的修复不是放弃共享而是把边界说清领域层尽量收住业务真相产品层负责生成自己的展示投影不能指望对旧数组原地改两下框架就能自动理解你的良苦用心。Nameo 目前仍在渐进收紧这条边界并不是已经完成了教科书式的纯 MVVM。这也是多端项目比 Demo 更值钱的地方难点往往不在“能不能调用 API”而在共享状态经过不同页面结构、导航和生命周期后还能不能保持一致。对 AI 应用也是同一条逻辑Phone/Watch 更像轻量采集入口Pad/PC 更适合整理和深度操作共享层维持知识与待办语义RAG 负责从知识中找到依据Agent 再决定要不要拆任务、调工具。多端页面不应该各自复制一套 AI 业务真相。八、Watch 不是缩小版 PhoneKV 同步也不是写一行 putWatch 最先逼我承认的一件事是通用组件能画出来不代表它适合圆屏。Nameo 的 Watch 首页采用纵向 5 屏ArcSwiper承载用户信息、今日摘要、知识速览、待办和闪卡。我没有继续拿普通Swiper硬撑。ArcSwiper面向弧形轮播平台能力覆盖触摸、导航点和表冠等切页方式其中表冠响应还依赖组件获焦Nameo 当前先用它解决五屏内容在圆形视口中的组织问题具体真机动作只按后面的专项证据陈述。组件换成圆屏专用形态之后UI 才像手表应用而不是有人拿剪刀把手机页面裁成了一个圆。更麻烦的其实是登录同步。Watch 不提供一套独立登录页而是由 Phone 通过分布式 KV 同步登录状态Watch 启动后读取再恢复本地账号资料。先把安全边界说在前面这里只能放最小必要状态或受保护的短期凭据绝不能把长期认证信息明文塞进去。下面只讲初始化和补发时序不会展示真实认证字段。至于怎样过期、撤销和解绑还得按正式安全方案设计不能把这段实现照搬成万能登录方案。架构图上看起来只有几根箭头Phone 登录 → 写入认证 KV → 分布式同步 → Watch 读取 → 恢复登录状态真机第一次却出现过“手机明明已经登录手表没反应”。根因不是 KV 不会同步而是时序Phone 的认证服务先恢复了登录态分布式同步服务还没初始化好登录回调只发布一次失败以后就没人再管。Watch 初装时又读得太早于是两边都很努力刚好彼此错过。Watch 端对应的恢复逻辑根据真实代码脱敏后大致如下awaitsyncService.init(context)awaitauthService.init(context)awaitauthService.loadAuthFromKvStore()syncService.setAuthChangeCallback((){authService.loadAuthFromKvStore()})scheduleAuthReload(2500)scheduleAuthReload(8000)后来的实现补了几层兜底Phone 在同步服务初始化完成后重新发布当前登录态Phone 发现远端设备或重新回到前台时再次补发Watch 监听登录状态 key 变化Watch 启动后和回前台进行少量延迟重读。登录状态数据和知识卡数据会分开处理退出登录也有单独标记。补发与重读必须保持幂等正式生产还要处理版本、过期、撤销和旧值覆盖延迟重读只是兜底不是一致性协议。时序跑通也不等于安全工作结束最小权限、凭据保护和设备解绑还得单独设计。这段代码不如架构图优雅但它很真实多设备的上线顺序不可控不能把“发过一次”当成“对方一定收到”。这些不是纸上设计。我在 HUAWEI WATCH 5 上把摘要、速记、待办、知识速览、闪卡和设置都完整走过后来又拿 Watch 5 和 Mate 60 Pro 专门联调了分布式 KV 登录、用户名和头像同步。也正是这次真机联调才让我碰到了前面那个“手机已经登录手表却没反应”的时序问题。九、同一个 HAP还是独立 HAP我现在只问五个问题以后再做多端技术选型我不会先问“能不能复用”而是按顺序问不同设备上的核心任务是否相同页面结构和主要交互是否相似自适应伸缩、折行或响应式断点能否解决输入方式、窗口生命周期和系统能力是否已经明显不同强行共享后产品层的条件分支是否开始破坏可读性和测试成本对应的决策大致是任务相同、结构相似 └─ 同一 HAP 自适应 任务相同、结构会随窗口改变 └─ 同一 HAP 响应式 Shell 任务、交互、窗口和功能范围明显分叉 └─ 产品层独立必要时独立 HAPPhone/Pad 是第二种PC 和 Watch 更接近第三种。这三行表示主要策略不是互斥的 API 清单。同一页面经常会先在断点处切换结构再用拉伸、隐藏、折行等能力完成局部自适应。但这不是所有项目的标准答案。一个只展示新闻列表的 PC 端可能完全没必要独立 HAP一个重度生产力 Pad 应用也可能最终值得拆开。架构选择必须跟着产品职责和未来重点走不是照着 Nameo 的目录抄作业。十、正式复盘这次多端拆分最终让我确定了四条原则先定义每种设备上的用户任务再讨论页面与代码复用。断点服务于窗口不要用设备名称代替布局判断。common/features共享业务语义products尊重页面、导航、输入和生命周期差异。多设备同步不能只在登录回调里“发一次就算了”还要处理服务初始化、设备上线和回前台的时序。复用率不是越高越好。真正应该放在一起的是那些因为同一个原因而变化的代码。这篇解决的是“同一套能力应该在哪台设备上怎样出现”。下一篇我们继续往 AI 深水区走聊天机器人、RAG、Workflow、Agent 到底差在哪儿Nameo 为什么在六月准备提审时又因为一个多跳问题返工这次不聊“接个大模型 API 就算 AI 应用”聊企业真正敢用的 RAG 和 Agent 边界。延伸阅读HarmonyOS 官方《一次开发多端部署概览》HarmonyOS 官方《多设备工程部署与发布》HarmonyOS 官方《响应式布局》HarmonyOS 官方《创建弧形轮播ArcSwiper》HarmonyOS 官方《电脑应用开发》HarmonyOS 官方《智能穿戴应用开发》