ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flutter适配OpenHarmony:基于AtomGit的版本管理实践

Flutter适配OpenHarmony:基于AtomGit的版本管理实践 这个系列是记录我把一套 Flutter 应用从普通 Android/iOS 目标扩展到 OpenHarmony 平台的过程。DAY 1 我把开发环境跑通、让空白项目在模拟器里亮了起来DAY 2 反倒没急着写界面而是先把代码托管、分支策略和备份机制定下来。原因很简单适配 OpenHarmony 的过程中你会反复改引擎版本、换插件、动原生桥接代码没有一套干净的版本管理后面每个 bug 都会变成灾难。这篇就来聊聊我最终选定 AtomGit 来做项目托管的具体理由以及从零到一的操作过程。我一开始天真地以为 Flutter 写鸿蒙就是换个编译目标真正动起手来才发现Flutter 系统架构里的渲染引擎、平台通道、插件注册方式都要重新审视。所以 DAY 2 这个选择不是偷懒恰恰是给后面所有折腾铺路。1. 先建仓再写码为什么 DAY 2 要先折腾版本管理1.1 适配 OpenHarmony 是个高试错过程写普通 Flutter 应用你大概率不需要那么严谨的版本策略flutter create 以后一路写业务最多隔几天 commit 一次。但一旦涉及 OpenHarmony 适配情况就变了。你会遇到 Flutter 引擎对鸿蒙的兼容性、平台通道的重新封装、第三方插件缺失导致要在原生侧重新实现等一堆问题。我实测一个上午能改出七八个不同的崩溃版本如果没有 git你想回退到半小时前那个还能跑的状态基本只能靠记忆非常痛苦。所以 DAY 2 的核心目标不是学会 git 的全部命令而是建立一套想怎么改就怎么改、随时能回退的安全网。这对我来说是继续往下做适配的前提。后面真正进入业务代码阶段这套安全网会帮我把尝试新方案和保住稳定成果这两件事彻底分开。1.2 为什么我选了 AtomGit说实话一开始我考虑过继续用 GitHub。项目已经在上面团队习惯也都在。但这次的目标平台是 OpenHarmony相关插件、引擎分支、鸿蒙侧 SDK 的适配代码很多都发布在开源生态平台或开放原子基金会周边。AtomGit 是开放原子开源基金会旗下的代码托管平台OpenHarmony 生态相关的项目、样例代码和 CI 模板在那边找起来很顺手社区里经常能刷到其他团队做的鸿蒙适配经验。另一个很现实的因素是我平时实际网络环境中访问 GitHub 的连接稳定性不太理想频繁拉取依赖、推送大文件时尤其明显。AtomGit 的访问速度明显更稳。这种平台选型没有绝对的好坏适合才是关键。如果项目主要在 Windows 和 macOS 之间来回切换一个连接稳定、push 不卡顿的远程仓库能省掉大量无效等待。1.3 对比 GitHub / Gitee 后的选择逻辑我简单列一下几个平台的使用体会表格不涉及任何立场纯粹是个人场景下的感受平台优势不太顺手的地方我的场景GitHub生态最大、模板多实际网络连接不稳定、Actions 速度看脸保留为主适合做镜像备份Gitee访问快、用户量大部分功能限制、平台风格偏传统可以做远程备用镜像AtomGit开源基金会背景、OpenHarmony 生态集中社区规模还在增长作为本轮适配的主仓这个表格可以作为参考。核心逻辑是高频 push、需要频繁跑 CI、依赖鸿蒙生态样例的地方放在 AtomGit 最顺GitHub 保留一份镜像用于备份不影响日常开发。如果说得再直白一点就是别把鸡蛋放在一个篮子里但主力仓库一定要放在自己操作最顺手的地方。2. 环境准备AtomGit 账号、SSH 密钥和本地 Git 配置2.1 注册账号与个人主页注册过程本身没啥特别的浏览器打开 atomgit.com按提示用手机号或者邮箱注册完成平台要求的验证就行。注册完之后建议做两件事一是把用户名固定下来后面仓库地址里会反复出现别取那种又长又难记的二是顺手在个人设置里补充一下公开资料因为你会发现 Issue、PR、评论里都会显示这个名字。如果你打算做开源个人主页上放上项目列表和联系方式会很加分。如果只是自己管理私有项目那就无所谓了怎么方便怎么来。我自己的习惯是主页保持简洁只放项目链接和一个能联系到我的邮箱避免无关信息干扰。2.2 本地 Git 的基本配置接下来是本地环境。老生常谈但经常有人漏git 安装完以后第一件事是设置 user.name 和 user.email而且要用你 AtomGit 账号绑定的邮箱。这一步漏了会导致提交记录里显示一串乱乱的 unknown 用户后续核对 commit 完全对不上人。git config --global user.name 你的名字 git config --global user.email 你的邮箱 git config --global credential.helper store最后一行 credential.helper store 是让 Windows 或部分 Linux 环境记住凭据省得每次 push 都要重新输密码。注意这是全局配置如果在公司机器上想隔离权限也可以去掉 --global单独给某个仓库设置。设置完之后可以执行git config --list检查一下有没有写对。2.3 SSH Key 的生成与绑定连接 AtomGit 我强烈建议走 SSH 而不是 HTTPS。生成密钥很简单在终端里执行ssh-keygen -t ed25519 -C 你的邮箱一路回车就行默认会在 ~/.ssh/id_ed25519 下生成私钥和 id_ed25519.pub 公钥。用编辑器打开 .pub 文件把内容整行复制然后去 AtomGit 的设置页面找到 SSH Keys 入口粘贴保存。生成 SSH Key 时如果设置了 passphrase每次拉取推送会要求输入个人开发图省事可以留空但团队环境建议设置并配合 ssh-agent 使用。绑定以后测试一下ssh -T gitatomgit.com看到类似成功提示说明 SSH 通道已经通了。这一步非常值得花两分钟验证。我见过不少同事复制公钥时把换行符也复制进去导致验证失败所以粘贴时最好用纯文本模式确认首尾没有多余空格。2.4 SSH 和 HTTPS 怎么选很多人习惯用 HTTPS 克隆。HTTPS 的优点是企业代理环境下容易放行端口 443 基本不会被特殊处理缺点是凭据管理相对麻烦。SSH 的好处是配置一次之后手工 push 不需要再输用户名密码缺点是部分公司网络环境可能不放行 22 端口。我个人的建议是本地开发优先 SSH如果公司网络不允许再退化到 HTTPS 并使用访问令牌。AtomGit 的令牌在个人设置里的访问令牌入口可以生成clone 时仍需按提示输入。从使用成本看SSH 是一次性配置、长期受益HTTPS 是网络受限时的备选方案两者不冲突甚至可以在同一台机器上并存。3. 在 AtomGit 上创建 Flutter for OpenHarmony 仓库3.1 新建仓库的关键选项怎么填进入 AtomGit 首页点新建仓库就会进入表单。这一页有几个字段需要注意仓库名这个会出现在 clone 地址里。用 flutter-ohos-demo 这种带连字符的名字比 my_project 清晰得多。描述填上Flutter for OpenHarmony 适配实验仓库这种一句话说明以后自己翻仓库列表时一眼能认出来。可见性刚开始建议私有。适配过程中会涉及平台通道代码、签名配置、密钥文件虽然最终可能开源但开发阶段少给自己惹麻烦。初始化选项我建议在创建时勾选生成 README、.gitignore、许可证。不一定每个都需要但 README 和 .gitignore 在后续 push 时能减少很多冲突。私有可见性这个决策很实用。鸿蒙适配过程中会临时存放一些 keystore、签名配置、甚至本地的 debug 证书虽然最终可能都不需要提交但私有仓库能避免不小心外泄。等适配稳定、确定哪些文件可以公开后再一键切换成公开也不迟。3.2 本地项目初始化与首次推送如果本地已经有一个 Flutter 项目最稳妥的做法是在项目根目录打开终端先初始化本地仓库然后关联到 AtomGit 远程。git init git add . git commit -m chore: init flutter project for openharmony adaptation git branch -M main git remote add origin gitatomgit.com:{用户名}/{仓库名}.git git push -u origin main注意如果你在网页端勾选了 README 初始化远程仓库已经有了一次提交这时本地直接 push 会报 non-fast-forward。解决办法是先拉取合并git pull origin main --rebase git push -u origin main用 --rebase 而不是常规 merge是为了让本地提交接到远程提交后面历史更线性后面做 code review 时每次 PR 的改动会清楚很多。这个细节新手容易忽略但养成习惯后收益很大。3.3 一个可直接抄的 Flutter .gitignoreFlutter 项目里最容易被不小心提交进去的文件我踩过的坑包括 build 目录、.dart_tool、.idea、.vscode 下的用户配置还有 Android 和 iOS 生成的临时产物。下面这份是我实际在用的模板# Flutter/Dart .dart_tool/ build/ .flutter-plugins* .packages *.iml # IDE .idea/ .vscode/ *.swp # 系统文件 .DS_Store Thumbs.db # 签名与本地配置 *.keystore *.jks *.p12 key.properties local.properties # 鸿蒙侧构建产物 oh_modules/ *.hap *.har务必注意key.properties、keystore 这类文件一旦提交到公开仓库签名密钥就泄露了。别问我怎么知道的。如果你尝试过把已有的 Android 工程嵌入 Flutter 页面或者反过来做还会多出一堆 Gradle 缓存和中间产物建议同样忽略。.gitignore 不是写一次就完事项目后期加了新类型文件要及时补进去。3.4 推完之后先做一次全流程验证仓库推送成功后别急着关终端顺手把流程完整跑一遍换一个目录重新 clone 一份打开项目确认能正常运行flutter pub get拿页面上公开的 README 渲染确认远程内容没问题。有些开发者只在 src 里工作从没验证过 clone 出来的干净副本结果同事或另一台设备 clone 完直接编译失败这种问题越早发现越好。我在 macOS 上 clone 到另一个目录跑过一次模拟器确认 Dart 依赖都能拿到才算真正把仓库可用这件事落实。这个验证过程花不了十分钟但能把本地能跑和仓库能复用这两件事彻底对齐避免后续陷入我本地明明没问题的尴尬。4. 日常协作里真正高频的 Git 操作与分支流4.1 分支策略让 main 永远能编译适配 OpenHarmony 很容易让 main 分支变成一锅粥。我的建议是最小分支策略main 分支只保持最近一个能正常编译、能跑起来的版本。任何新实验无论是换 Flutter 引擎分支、写新的平台通道、还是升级鸿蒙 SDK都开一个 feature 分支去试git checkout -b feature/ohos-eventchannel # 写代码、测试 git commit -m feat: add eventchannel for ohos native event git checkout main git merge feature/ohos-eventchannel这样做的理由很朴素HAP 构建产物经常因为一个原生依赖版本更新就整个挂掉如果你直接在 main 上横冲直撞想回退时可能连上一次能跑的提交都找不到。开分支的成本极低但保命效果极好。我自己在适配阶段几乎每动一个原生模块就开一个分支试完合并不行就删分支重来。4.2 提交信息别糊弄规范化写法我见过太多update、fix bug这种提交信息。每次看 log 都像在猜谜。建议使用统一的类型前缀feat新功能fix修复问题chore构建、工具链等杂事docs文档refactor重构不改行为perf性能优化正文里一定要写清楚为什么。比如我提交 fix: adapt CustomEventChannel for OpenHarmony 时会顺便在提交信息里注明之前的注册入口依赖了 iOS 侧的 MainViewController 时序鸿蒙侧需要在 EntryAbility 的 onCreate 之后才能注册。这样几周后再回看提交历史一眼就能知道改动背景。不要小看这个习惯。适配项目最痛苦的往往不是代码本身而是当初为什么要这么改。提交信息就是给未来的自己留的便条。尤其是涉及 Flutter 组件通信、Navigator 生命周期这类容易埋雷的地方记录下当时的判断依据排查问题时能少走很多弯路。4.3 小步提交与 Tag 打点我给自己定的规矩是每完成一个可编译的小里程碑就提交一次每完成一个阶段就打个 tag。比如适配初期可以这样打点git tag v0.1-ohos-bootstrap git push origin v0.1-ohos-bootstrap为什么要打 tag因为 Flutter 版本升级、OpenHarmony SDK 版本升级经常带来不可控的连锁反应。有了 tag任何时候想回到某个已知稳定的状态一条命令就能完成。你不需要记住复杂的 commit 哈希tag 就是给版本起的名字。特别是当安卓原生项目嵌入 Flutter 页面这个需求加入后原生和 Flutter 的耦合变深回滚点必须非常明确。我习惯把 tag 命名为 v0.1-ohos-xxx 这种可读性强的格式一眼就能看出这是鸿蒙适配初期的哪个阶段。等整个适配闭环跑通再回过头整理正式版本号也不迟。4.4 多设备同步的正确姿势很多 Flutter 开发者手上有不止一台机器公司在 Windows家里是 macOS。AtomGit 作为远程仓库天然解决同步问题。但有个细节值得注意不要在 push 前不看状态就盲目执行。稳妥的流程是git status # 先看有哪些改动 git pull --rebase # 同步远程改动 git push # 推送自己的改动如果你忘了 pull 直接 push大概率会撞上 rejected 提示。面对这类提示别慌先查一下远程是不是有提交。如果确实只是自己两台机器之间的同步git pull --rebase基本能解决一切。在 Windows 和 macOS 之间来回切换时我还会留意行尾符差异虽然 Git 通常能自动处理但偶尔也会出现整文件 diff 的情况这时候先检查 .gitattributes 配置比手动改代码高效得多。5. 从个人项目走向协作Issue、PR 和 CI 接入5.1 用 Issue 管理适配任务清单OpenHarmony 适配往往不是单线程任务我把手头的待办全挂在 Issue 里字体渲染待验证、事件通道待重构、推送插件缺鸿蒙实现。这样做有几个好处每件事的上下文都被记录下来哪些完成哪些没有一眼可知如果之后有人加入协作Issue 就是最自然的任务交接列表。写 Issue 时我会按复现步骤 期望行为 实际行为 环境信息来写。特别是环境信息Flutter 版本、OpenHarmony SDK 版本、引擎分支版本都必须写清楚因为同样的代码在不同版本上的表现可能完全不同。我见过最离谱的 Issue 就是只说跑不起来三个字这种信息对排查毫无帮助。5.2 Pull Request 到底是给谁看的一个人开发时PR 看起来有点多余但我的经验是哪怕是自己合并自己的 PR也要走一遍完整流程。原因是 PR 页面会展示 diff你能以审查者的身份重新审视每一行改动。尤其对于平台桥接代码这种二次审视能抓住不少低级问题。比如 EventChannel 方法的命名、日志级别、生命周期钩子放的位置都很容易在自审时发现问题。如果团队协作PR 描述要写清楚三件事这个 PR 解决什么问题、改动了哪些文件、如何验证。Code Review 时重点看的是原生侧代码和 Flutter 侧注册时机这些地方出了问题通常不会第一时间报错而是表现为偶发异常。我自己在 review 时经常盯着生命周期相关的改动不放手因为这类问题在鸿蒙适配里出现频率实在太高了。5.3 接一个最简单的 CI 工作流版本管理最终要服务于自动化。AtomGit 提供了基于 YAML 配置的流水线功能可以在推送时自动执行flutter analyze和flutter test至少在合并前把静态问题挡在门外。我没有在这里贴一份固定模板因为不同分支的 Flutter 环境差异很大特别是 OpenHarmony 引擎分支每个人的 SDK 路径和依赖源可能都不一样。建议的接入顺序是第一步只跑 Dart 层的分析和单测不涉及鸿蒙构建因为这一步对环境要求最低第二步再尝试在流水线里执行鸿蒙侧构建此时需要提前在平台侧配置好 SDK 路径、环境变量和签名文件。优先级一定是先保证 analyze 和 test 通过鸿蒙构建放到后面再说。跑了 CI 之后你会发现很多低级错误在推送阶段就被拦住了而不是等到合并后才爆出来。5.4 把适配代码回馈给上游插件一旦你在自己仓库里把某个 Flutter 插件的 OpenHarmony 适配跑通了可以考虑把适配代码以 PR 形式回馈给上游。这不只是为爱发电现实中这些插件很可能就是你以后要持续维护的。把适配过程挂在 Issue 里把 commit 记录整理清楚上游合并时你的工作量也能得到体现。对接插件时最常见的坑是事件通道EventChannel在鸿蒙侧的注册时机以及方法通道MethodChannel在页面生命周期重启时恢复。这些内容在主干代码里往往没有专门文档需要靠你自己 debug 后沉淀成注释或者写成文档提交上去。我在适配过程中遇到的 Flutter 页面切换后状态丢失问题最后就是在这些插件代码里找到了根因——原生容器在重建时没有重新注册通道。6. 常见问题与排查技巧实录6.1 推送失败类问题速查下面这张表是我在实际使用 AtomGit 过程中遇到的推送相关问题的汇总按出现频率排序现象可能原因解决思路Permission denied (publickey)SSH 密钥没绑定或绑错机器重新查看 ~/.ssh/id_ed25519.pub到平台重新添加non-fast-forward 推送被拒远程有本地不知道的提交先 git pull --rebase解决冲突后再 push卡在输入密码用了 HTTPS 且未存 token改用 SSH或配置 credential helper 保存 token大文件 push 超时误提交了 build 目录或 HAP 包删除大文件重写 commit 历史或用 LFS推送失败时第一反应不要想着强制覆盖尤其是协作仓库先确认远程状态、看看最近几条提交是谁写的再决定下一步。强制 push 会把别人的工作推没这种事干一次团队信任就没了。就算只是个人仓库我也建议养成先 pull 再 push 的习惯避免养成依赖强推的坏毛病。6.2 Flutter SDK 版本与提示不匹配很多人在配置 Flutter 开发环境时见过这句提示the current configured flutter sdk is not known to be fully supported。尤其是当你为了适配 OpenHarmony 换了引擎分支时IDE 里 Flutter 版本识别就会出现这种警告。我的处理思路是不忽略警告但也不必被它吓住。先去确认当前 Flutter 版本是否满足项目依赖要求。如果项目里既有 Android 构建又有鸿蒙构建建议用 fvmFlutter Version Management锁定每个项目需要的 Flutter 版本避免不同机器上环境漂移。最简单的做法是在仓库根目录写清楚版本要求或者在 README 的环境说明里注明 Flutter 版本和鸿蒙 SDK 套件版本。另外如果你同时维护着 iOS 构建Xcode 升级后经常出现很多 Flutter 包报版本低的现象那是另一个独立的兼容性问题排查时别和鸿蒙适配混在一起。6.3 Gradle 插件配置方式迁移用 Flutter 创建的项目默认在 android/settings.gradle 里会有一段插件声明。但如果你把项目升级到比较新的 Gradle 版本经常会在构建时看到类似 you are applying flutters main gradle plugin imperatively using the apply script 的提示。这其实是构建脚本在呼吁你改用 plugins DSL 的方式去声明 Flutter Gradle 插件而不是用 apply from 的旧方式。处理方法并不难在 android/settings.gradle 里加上 Flutter 插件声明并移除 build.gradle 里对应的 apply 脚本。由于 Flutter 版本不同具体写法也会有差异最稳的方案是让 flutter create 重新生成一个同版本的新项目然后把新项目里的 android 构建脚本搬过来做对照别凭记忆手抄。这种问题在鸿蒙适配过程中很容易被忽略因为主要精力都在原生侧但一旦真的踩中排查起来非常费时间。6.4 文件名大小写与缓存问题在 Windows 上开发 Flutter如果代码里引用了 EventChannel.dart但磁盘上实际文件名是 eventChannel.dart拉取到 macOS 或 Linux 上就会编译失败。Windows 默认不区分大小写所以这种问题在自己机器上根本发现不了。处理办法修改文件名后执行 git mv 确保 Git 记录变更同时在仓库根目录设置git config core.ignorecase false让 Git 开始跟踪大小写变化。同样的道理改完依赖、升级版本后如果 Flutter 命令表现异常优先执行flutter clean并删除 build、.dart_tool 目录后再尝试很多诡异问题其实是缓存作的妖。实践里这个排查思路能解决 70% 的我改了代码但行为没变类问题。DAY 2 的内容说实话没有写任何一行业务页面但它给后面几天的适配工作省了太多事。我个人实际操作下来的感受是版本管理这件事配置成本远没有我们想象中那么高反而是出了问题以后想补救的成本高得吓人。如果你也在做 Flutter 往 OpenHarmony 迁移别管项目多小先把仓库、分支、SSH、.gitignore 这几件事弄利索。后面每一次崩溃的时候你都会感谢昨天把安全网搭好的自己。最后再分享一个小技巧给每次能正常跑通的版本打上 tag哪怕 tag 名字很丑。等 Flutter 引擎或鸿蒙 SDK 升级出问题的时候你会明白一个能一键回去的稳定版本比任何花哨的文档都管用。
返回列表