現(xiàn)自動(dòng)化資源索引與極簡(jiǎn)引用)
把項(xiàng)目往鴻蒙遷移的時(shí)候我遇到的第一批麻煩不在業(yè)務(wù)邏輯而在最不起眼的資源引用上。Flutter 工程里的圖片、圖標(biāo)、動(dòng)畫、字體文件散落在幾十個(gè)模塊里原本靠手寫字符串路徑維持秩序規(guī)模一上來就失控刪了一張不再使用的背景圖構(gòu)建沒報(bào)錯(cuò)但線上某個(gè)頁面灰了設(shè)計(jì)師改了一版 icon 文件名全局替換漏了兩處新同事接手看著assets/images/home/ic_home_selected.png這種字符串根本不敢動(dòng)。就在這個(gè)節(jié)骨眼上我開始把Flutter 三方庫 gator這套資產(chǎn)管理方案引入鴻蒙工程用它做自動(dòng)化資源索引生成最終在鴻蒙端實(shí)現(xiàn)了極簡(jiǎn)資源引用。這篇文章就把完整的適配思路、落地步驟和踩過的坑展開聊聊給同樣在做 Flutter 鴻蒙化適配的團(tuán)隊(duì)一個(gè)可復(fù)現(xiàn)的參考。1. 為什么要?jiǎng)舆@套資源體系一場(chǎng)遷移引發(fā)的連鎖問題1.1 Flutter 資源管理的日常戰(zhàn)場(chǎng)很多 Flutter 團(tuán)隊(duì)對(duì)資源管理一直處于能跑就行的狀態(tài)。pubspec.yaml 里掛一串 assets 目錄代碼里用Image.asset(assets/images/xxx.png)硬編碼路徑。這種模式在小項(xiàng)目里沒毛病但一旦模塊多、設(shè)計(jì)師頻繁出圖、品牌換版問題就浮出水面了。我統(tǒng)計(jì)過手頭項(xiàng)目的資源分布圖片和圖標(biāo)加起來接近 1400 個(gè)文件分布在 6 個(gè)一級(jí)目錄下。String 類型的資源路徑散落在數(shù)十個(gè) dart 文件里沒有索引、沒有補(bǔ)全、沒有編譯期檢查。重構(gòu)一個(gè)目錄名等于人工核對(duì)所有引用點(diǎn)。最難受的是 Flutter 對(duì)資源缺失的處理方式運(yùn)行時(shí)才報(bào)錯(cuò)構(gòu)建時(shí)完全靜默。也就是說路徑寫錯(cuò)了開發(fā)機(jī)上往往看不出來只有走到那個(gè)頁面、觸發(fā)那個(gè)狀態(tài)才會(huì)崩。用 Flutter 的朋友應(yīng)該都見過類似Unable to load asset的紅色報(bào)錯(cuò)日志頭常帶error:flutter/runtime/dart_vm_initializer.cc之類的系統(tǒng)幀真正有價(jià)值的信息在后面那行ImageCodecException。1.2 字符串路徑方案在鴻蒙遷移期的放大效應(yīng)本來這套手寫路徑方案雖然難受但勉強(qiáng)能維持。真正讓我決定徹底改造的是這次鴻蒙適配。鴻蒙側(cè)的 Flutter 工程和 Android/iOS 工程在資源交付上有本質(zhì)區(qū)別。你在鴻蒙原生側(cè)看到的資源體系是rawfile、media這類目錄而 Flutter 側(cè)的資產(chǎn)依然走 pubspec.yaml 聲明。兩邊是隔離的Flutter 的Image.asset讀取的是 Flutter 資產(chǎn)包里的文件和鴻蒙原生的資源文件互不相干。這意味著遷移時(shí)你不能簡(jiǎn)單地把資源搬過去就完事還要保證 Flutter 側(cè)聲明的路徑和代碼里寫死的字符串一一對(duì)應(yīng)。這個(gè)對(duì)應(yīng)關(guān)系在原有項(xiàng)目里已經(jīng)靠人工維護(hù)遷移到鴻蒙之后觸點(diǎn)更多、驗(yàn)證鏈路更長(zhǎng)出錯(cuò)概率成倍放大。每次編譯鴻蒙版本我都要花時(shí)間核對(duì)資產(chǎn)清單查哪些圖片沒進(jìn)包、哪些路徑在新舊版本之間有差異。遷移進(jìn)度被卡在資源核對(duì)上這顯然不是業(yè)務(wù)本身的問題是工程基建欠了債。與其逐個(gè)人肉盯不如引入一個(gè)能在鴻蒙工程里自動(dòng)化生成資源引用的工具。這就是我選擇 gator 的起點(diǎn)。2. gator能管到什么程度定位、邊界與鴻蒙適配可行性2.1 gator 的作用邊界從 pubspec 到 Dart 代碼的自動(dòng)翻譯先拆解 gator 到底做了什么。它的核心思路一句話就能說清讀取 pubspec.yaml 中聲明的資產(chǎn)配置掃描指定目錄下的真實(shí)文件然后生成一套強(qiáng)類型 Dart 類把每個(gè)資源封裝成編譯期可見的屬性。生成之后你不再寫Image.asset(assets/images/home/ic_home.png)而是寫AssetImages.home.icHome。路徑字符串變成了帶命名空間的屬性訪問編譯期就能發(fā)現(xiàn)拼寫錯(cuò)誤和缺失文件。如果目錄里刪了一個(gè)文件重新生成代碼直接編譯不過問題暴露在 CI 階段而不是線上用戶手里。這里我要特意說清 gator 的邊界它只負(fù)責(zé) Flutter 側(cè)的資產(chǎn)管理不接管鴻蒙原生側(cè)的資源。它做的事是把人類維護(hù)資源路徑這件事自動(dòng)化而不是改變 Flutter 引擎的資源加載機(jī)制。理解了這條邊界鴻蒙適配的路就清楚了一半。2.2 適配鴻蒙不需要改造插件Dart 側(cè)與引擎?zhèn)鹊穆氊?zé)劃分很多團(tuán)隊(duì)一聽到鴻蒙化適配就默認(rèn)要寫原生插件、處理 platform channel其實(shí)這是慣性思維。Flutter 三方庫在鴻蒙的兼容性要分兩層看第一層是純 Dart 包。它只依賴 Dart SDK 和 Flutter framework 的 Dart 層 API不涉及任何原生代碼。這類包在鴻蒙 Flutter 環(huán)境里通??梢灾苯舆\(yùn)行因?yàn)轼櫭啥伺艿?Flutter 引擎雖然渲染層有自研改動(dòng)但 Dart 層的 API 是保持兼容的。第二層是帶原生實(shí)現(xiàn)的插件。比如依賴 Android 的toString、iOS 的UIKit或者通過 MethodChannel 調(diào)用系統(tǒng)能力的包這類必須要做鴻蒙原生插件適配。gator 屬于第一層。它本質(zhì)上是一個(gè)命令行工具加代碼生成器主要依賴analyzer、source_gen這類純 Dart 基礎(chǔ)設(shè)施不直接觸碰引擎能力。因此在鴻蒙 Flutter 工程里不需要為它開發(fā)鴻蒙原生插件只需要把它納入工程工作流即可。這是整個(gè)適配方案成立的前提也是我覺得值得寫出來的原因不是所有 Flutter 三方庫都要做鴻蒙化改造很多純 Dart 工具類庫遷移成本比想象中低得多。2.3 一條硬性前提Dart/Flutter SDK 版本匹配適配 gator 時(shí)真正要關(guān)注的是 SDK 版本約束。gator 這類代碼生成工具對(duì) Dart SDK 版本通常有明確要求比如支持的空安全版本、analyzer 版本兼容區(qū)間。鴻蒙 Flutter SDK 的 Dart 版本可能和官方 Flutter 的版本有細(xì)微差別安裝后第一件事就是確認(rèn)版本區(qū)間。我在實(shí)測(cè)中的建議是先跑dart --version看當(dāng)前鴻蒙 Flutter SDK 自帶的 Dart 版本再對(duì)照 gator 的 pubspec.yaml 中environment: sdk的聲明。如果發(fā)現(xiàn)版本不匹配不要硬裝優(yōu)先查是否有對(duì)應(yīng)版本的 gator 發(fā)版。這類純代碼生成工具對(duì) analyzer 接口比較敏感版本跨度大了會(huì)出現(xiàn)生成失敗或產(chǎn)物異常這是常見的第一道坎。3. 三步接入鴻蒙工程配置、生成、引用全流程3.1 環(huán)境準(zhǔn)備與安裝接入前需要確認(rèn)環(huán)境里能執(zhí)行 Dart 命令行工具。鴻蒙 Flutter 工程通常通過 DevEco Studio 安裝的 Flutter SDK 提供 Dart直接把 SDK 的 bin 目錄加到 PATH 即可。安裝 gator 有兩種方式。一種是作為工程的 dev dependency 加入 pubspec.yaml適合讓功能固定版本、CI 可復(fù)現(xiàn)另一種是全局激活適合本地快速使用。我自己的習(xí)慣是工程級(jí)引入這樣團(tuán)隊(duì)每個(gè)人拿到的版本一致。dev_dependencies: gator: ^x.y.z加入依賴后執(zhí)行flutter pub get拉取。提醒一句在鴻蒙工程里執(zhí)行 pub 相關(guān)命令時(shí)網(wǎng)絡(luò)環(huán)境要和官方 pub.dev 保持連通如果公司內(nèi)網(wǎng)有代理要提前配置好 PUB_HOSTED_URL 這類環(huán)境變量否則拉取容易失敗。3.2 pubspec.yaml 的資產(chǎn)目錄整理規(guī)范gator 生成代碼是建立在 pubspec.yaml 的 assets 聲明之上的。所以第一步是整理資產(chǎn)目錄制定一套全工程統(tǒng)一的命名規(guī)則。我建議的規(guī)范是這樣一級(jí)目錄按功能域劃分比如assets/images、assets/icons、assets/animations、assets/fonts不要搞一個(gè)assets平鋪到底。圖片資源用下劃線命名ic_home_selected.png這種形式方便生成代碼時(shí)做駝峰轉(zhuǎn)換。不用的資源及時(shí)清理gator 會(huì)掃描真實(shí)文件目錄里的孤兒文件如果還留在 pubspec 聲明里會(huì)生成多余的屬性看著礙眼也容易誤導(dǎo)后續(xù)維護(hù)的人。pubspec.yaml 里資產(chǎn)聲明的常見寫法是整目錄聲明flutter: assets: - assets/images/ - assets/icons/ - assets/animations/這里有個(gè)細(xì)節(jié)值得強(qiáng)調(diào)聲明目錄而不是聲明單個(gè)文件。gator 掃描時(shí)能完整遍歷目錄內(nèi)容新增文件不需要每次手動(dòng)改 pubspec只有新增一級(jí)目錄才需要更新聲明。這能省掉大量重復(fù)勞動(dòng)。3.3 gator 配置項(xiàng)拆解gator 本身提供了一套配置能力可以在 pubspec.yaml 里單獨(dú)建一個(gè)gator:配置塊也可以在工程根目錄放專門的配置文件。核心配置項(xiàng)包括配置項(xiàng)作用我的建議generated_dir生成代碼的輸出目錄輸出到lib/generated/與手寫代碼隔離gen_config是否生成資源清單映射建議開啟方便快速檢索class_name生成主類名統(tǒng)一用Asset前綴避免沖突exclude排除規(guī)則對(duì)*.json、*.md這類非運(yùn)行時(shí)資源做排除no_squash/squash是否目錄結(jié)構(gòu)折疊大目錄建議折疊避免類嵌套過深配置不是越多越好按團(tuán)隊(duì)實(shí)際需要來。核心兩個(gè)決定生成代碼放哪、類名取什么。這兩項(xiàng)定了之后基本不用再動(dòng)。3.4 執(zhí)行生成與產(chǎn)物落位配置完成后執(zhí)行生成命令。gator 的命令形式在不同版本略有差異常見的有dart run gator、dart run gator:run或者注冊(cè)成全局命令。建議以實(shí)際安裝版本的幫助輸出為準(zhǔn)先跑一次dart run gator --help確認(rèn)。執(zhí)行成功后會(huì)在lib/generated/下出現(xiàn)生成的資產(chǎn)類文件。這個(gè)文件應(yīng)該提交到 Git不要在 .gitignore 里忽略它。原因很實(shí)際如果本地生成了但 CI 上沒有生成步驟團(tuán)隊(duì)成員拉下來代碼編譯不過還得手動(dòng)跑一次平白增加摩擦。生成代碼提交到倉(cāng)庫里保證任何人 checkout 下來都是可編譯狀態(tài)。3.5 在鴻蒙 Flutter 頁面里落地引用生成完成之后代碼引用方式就從字符串路徑變成了強(qiáng)類型屬性。以一張首頁背景圖為例// 之前 Image.asset(assets/images/home/bg_home.png) // 之后 Image.asset(AssetImages.home.bgHome)屬性命名由工具根據(jù)文件路徑推導(dǎo)目錄層級(jí)對(duì)應(yīng)到類的嵌套結(jié)構(gòu)文件名轉(zhuǎn)成駝峰。編輯器里輸入AssetImages.就能自動(dòng)補(bǔ)全不認(rèn)識(shí)資源也能順著類名一路點(diǎn)進(jìn)去這種體驗(yàn)在手寫字符串時(shí)代是完全沒有的。4. 生成產(chǎn)物拆解極簡(jiǎn)資源引用是怎么變出來的4.1 典型的資產(chǎn)類代碼長(zhǎng)什么樣說實(shí)話第一次打開 gator 生成的代碼時(shí)我對(duì)它的印象是代碼量不小但結(jié)構(gòu)很規(guī)整。它會(huì)按資源類型分別生成不同的類圖片類、圖標(biāo)類、其他資產(chǎn)類。整體結(jié)構(gòu)類似這樣// 簡(jiǎn)化示例僅用于說明生成形態(tài) class AssetImages { const AssetImages._(); static const HomeImages home HomeImages._(); static const AssetImage bgLogin AssetImage(assets/images/bg_login.png); } class HomeImages { const HomeImages._(); static const AssetImage bgHome AssetImage(assets/images/home/bg_home.png); static const AssetImage icBanner AssetImage(assets/images/home/ic_banner.png); }注意這里的細(xì)節(jié)每個(gè)屬性不是簡(jiǎn)單的字符串常量而是AssetImage對(duì)象。這意味著你拿到的不只是路徑而是一個(gè)能直接喂給 ImageProvider 的現(xiàn)成對(duì)象。在使用時(shí)不需要再包一層Image(image: AssetImages.home.bgHome)也可以寫成Image(image: AssetImages.bgLogin)上面這個(gè)形態(tài)是我照著實(shí)際項(xiàng)目里生成的產(chǎn)物簡(jiǎn)化出來的不同版本類名和屬性類型可能有差異但核心思路一致資源引用從字符串常量升級(jí)為帶類型語義的實(shí)例對(duì)象。4.2 命名推導(dǎo)規(guī)則為什么 AssetImages.home.bgHome 的調(diào)用能成立想要用好生成的類必須理解命名推導(dǎo)規(guī)則。規(guī)則并不復(fù)雜資源文件去掉擴(kuò)展名以下劃線_或橫線-作為單詞分隔符轉(zhuǎn)成駝峰。文件所在的目錄層級(jí)映射為類的嵌套結(jié)構(gòu)。被多個(gè)組件共享的頂層資源掛在總類下目錄內(nèi)的資源掛在對(duì)應(yīng)子類下。舉例assets/images/home/ic_home_selected.png會(huì)推導(dǎo)為AssetImages.home.icHomeSelected。如果目錄里還有一個(gè)common/ic_close.png就推導(dǎo)為AssetImages.common.icClose。這套規(guī)則的可預(yù)測(cè)性很重要。團(tuán)隊(duì)里任何一個(gè)人看到一個(gè)路徑就能推出生成后的訪問形式反過來看到一個(gè)訪問表達(dá)式也能反推出文件在哪個(gè)目錄。命名約束帶來的好處是雙向的。4.3 異常情況與產(chǎn)物一致性生成工具不是萬能藥有幾個(gè)邊界我要提醒一是重復(fù)文件名。如果兩個(gè)不同目錄下存在同名文件比如images/a/loading.png和images/b/loading.png生成時(shí)可能出現(xiàn)屬性沖突。gator 會(huì)對(duì)子類命名做去重處理但為了不讓結(jié)果別扭最好在命名規(guī)范里就規(guī)避同名文件放到同一個(gè)目錄或者改名。二是生成時(shí)序問題。變更了 pubspec.yaml 的 assets 聲明后必須重新執(zhí)行生成命令生成代碼才會(huì)同步。如果只是往已有聲明的目錄里丟新文件也要重新生成。這個(gè)動(dòng)作建議固化進(jìn)開發(fā)流程否則會(huì)出現(xiàn)代碼引用了新生成的類但同事的本地還沒生成的編譯錯(cuò)誤。三是產(chǎn)物代碼的可讀性。生成代碼不追求可讀性它是給編譯器和開發(fā)者補(bǔ)全用的不需要人為修改。千萬不要手改生成文件所有變更都通過重新生成完成否則下次生成會(huì)被覆蓋。5. 鴻蒙適配期最常踩的坑鏈路排查與驗(yàn)證5.1 熱重載后圖片仍顯示舊資源我在鴻蒙側(cè)剛接入時(shí)遇到的第一個(gè)奇怪問題索引文件重新生成后修改了圖片內(nèi)容熱重載之后界面顯示的還是老圖。排查過程很有意思。Flutter 熱重載默認(rèn)只重跑 Dart 代碼資源文件變更并不在熱重載的監(jiān)聽范圍內(nèi)。開發(fā)階段改了圖片最穩(wěn)妥的做法是停掉應(yīng)用重新 run而不是指望熱重載。這個(gè)和是不是鴻蒙無關(guān)官方 Flutter 也這樣但遷移期大家注意力都在適配問題上很容易忽略這個(gè)老規(guī)矩。處理方式分兩種情況如果只是替換同名圖片文件重啟應(yīng)用即可如果新增了圖片文件除了重啟應(yīng)用還要重新跑一遍資源索引生成讓新資源進(jìn)入生成代碼的可見范圍。5.2 資產(chǎn)路徑含特殊字符導(dǎo)致 not found復(fù)現(xiàn) E/flutter 錯(cuò)誤的排查鏈路第二個(gè)坑最有代表性。當(dāng)時(shí)測(cè)試反饋某個(gè)圖標(biāo)不顯示日志里能看到 Flutter 資源加載失敗的報(bào)錯(cuò)日志頭部就是那種標(biāo)準(zhǔn)的error:flutter/runtime/dart_vm_initializer.cc開頭的框架幀往下翻能看到類似Failed to load asset的關(guān)鍵行。我的排查鏈路是這么走的先定位報(bào)錯(cuò)的資源路徑。錯(cuò)誤日志里通常會(huì)帶路徑檢查這個(gè)路徑是否真實(shí)存在于 assets 目錄。確認(rèn)文件存在后檢查 pubspec.yaml 的 assets 聲明是否覆蓋到了該目錄。如果聲明的是具體文件列表漏加新文件是常見原因。再檢查路徑里有沒有中文、空格、百分號(hào)等特殊字符。我這次的問題就是設(shè)計(jì)師給文件夾起了中文名Android 側(cè)測(cè)試通過但鴻蒙側(cè)的打包鏈路對(duì)這類路徑的處理更敏感導(dǎo)致資源沒正確進(jìn)包。最后重新執(zhí)行資源索引生成確認(rèn)生成代碼里解析出來的路徑和實(shí)際文件路徑完全一致。修復(fù)方式不止一種我選的是最治本的方案資源文件命名回歸 ASCII 字符集統(tǒng)一用下劃線和小寫字母從源頭杜絕特殊字符。這一步看起來是管得寬但事實(shí)證明它對(duì)整個(gè)團(tuán)隊(duì)的資源管理幫助巨大——不光鴻蒙側(cè)Android 和 iOS 側(cè)也少了很多潛在坑。5.3 混用 PlatformView 的場(chǎng)景要單獨(dú)驗(yàn)證鴻蒙 Flutter 工程里地圖、相機(jī)這類能力通常要借助 PlatformView 橋接原生組件。這些場(chǎng)景的資源加載路徑和純 Flutter 頁面不同Android 端可以用原生 View 顯示圖片鴻蒙端也要各自實(shí)現(xiàn)Flutter 的 AssetImage 并不自動(dòng)適用于所有混用場(chǎng)景。我的建議是涉及 PlatformView 的頁面資源引用依然走 gator 生成的索引但渲染驗(yàn)證要單拎出來做一遍。具體來說寫一個(gè)頁面專門羅列各種邊界場(chǎng)景圖片混在原生組件上層、圖標(biāo)嵌在平臺(tái)視圖中、半透明資源疊加。每次資源體系變更在這個(gè)頁面過一遍比上線后讓用戶踩雷強(qiáng)得多。5.4 一線兜底手段資產(chǎn)引用冒煙測(cè)試除了人工驗(yàn)證還可以寫一個(gè)輕量的資產(chǎn)冒煙測(cè)試頁面對(duì)生成的索引類做一次系統(tǒng)性加載。思路是把所有生成的資源按目錄遍歷一遍逐個(gè)用precacheImage提前加載到緩存加載失敗的打點(diǎn)上報(bào)。這段邏輯本身不復(fù)雜但價(jià)值很高。它把某個(gè)資源路徑斷了這個(gè)問題從偶發(fā)運(yùn)行時(shí)錯(cuò)誤變成了啟動(dòng)階段可察覺異常。CI 里也可以掛一條命令跑冒煙再掃一眼日志關(guān)鍵字基本能做到資源問題不帶到線上。6. 把 gator 納入自動(dòng)化體系CI 聯(lián)動(dòng)與團(tuán)隊(duì)協(xié)作習(xí)慣6.1 CI 流水線中自動(dòng)生成與校驗(yàn)接入 gator 之后我把資源索引生成動(dòng)作掛進(jìn)了 CI。流水線里的關(guān)鍵步驟是這樣設(shè)計(jì)的flutter pub get dart run gator # 重新生成資源索引 flutter analyze # 靜態(tài)檢查發(fā)現(xiàn)資源引用錯(cuò)誤會(huì)直接失敗 flutter build hap # 構(gòu)建鴻蒙產(chǎn)物這里flutter analyze是關(guān)鍵一環(huán)。因?yàn)樯傻拇a是編譯期可見的如果有人在業(yè)務(wù)代碼里寫了一個(gè)不存在的資源引用analyze 會(huì)直接報(bào)錯(cuò)整個(gè)流水線在編譯階段就紅掉根本走不到打包。這一步把資源問題的發(fā)現(xiàn)時(shí)點(diǎn)從運(yùn)行時(shí)提前到了CI 時(shí)成本幾乎為零收益非常直接。另外提一句產(chǎn)物形態(tài)。鴻蒙側(cè)最終集成 Flutter 工程時(shí)依賴的交付物可能是 HAR 或 AAR 這類包資源打包路徑和源碼工程不完全一樣。CI 里跑完生成后要注意對(duì)比產(chǎn)物包內(nèi)的資源清單確認(rèn)索引指向的文件都進(jìn)了包。我在早期就遇到過索引生成了、編譯過了、但產(chǎn)物包里資源缺失的情況所以推薦在流水線里加一道產(chǎn)物內(nèi)容檢查。6.2 命名即約束團(tuán)隊(duì)接入的關(guān)鍵細(xì)節(jié)工具落地最大的阻力通常不是技術(shù)而是協(xié)作習(xí)慣。gator 把資源訪問變成了類屬性但類屬性的命名和結(jié)構(gòu)是生成的依據(jù)就是文件命名。想讓團(tuán)隊(duì)順暢使用必須先把文件命名規(guī)范定死。我收編的規(guī)范簡(jiǎn)單到有點(diǎn)粗暴但執(zhí)行效果很好所有資源文件名只允許小寫字母、數(shù)字、下劃線。英文單詞用下劃線分隔禁止連字符和空格。目錄名和文件名都要能表達(dá)清晰語義禁止無意義縮寫。定完規(guī)范之后gator 生成出來的類名天然具有可讀性。設(shè)計(jì)師傳新圖時(shí)按模板命名開發(fā)引用時(shí)靠編輯器補(bǔ)全審代碼時(shí)看AssetImages.xxx就能判斷資源歸屬哪個(gè)模塊。規(guī)范的約束價(jià)值被工具放大了工具的便利又被規(guī)范降低了理解成本兩者是配合關(guān)系。6.3 邊界之外的提醒什么不該交給 gator最后說點(diǎn)反直覺的經(jīng)驗(yàn)。gator 很好用但并不是所有資源都應(yīng)該往它里面塞。第一類是網(wǎng)絡(luò)資源。需要遠(yuǎn)端下發(fā)、運(yùn)行時(shí)拼接 URL 的圖片不應(yīng)該硬編碼進(jìn)資源索引它們的生命周期和代碼包不一致。第二類是密鑰、配置類文件。含敏感信息的文件預(yù)處理之后才進(jìn)入資產(chǎn)目錄而不是直接裸放在工程里。第三類是頻繁動(dòng)態(tài)變化的運(yùn)營(yíng)素材。這類素材建議走分發(fā)通道而不是每次發(fā)版打包進(jìn) Flutter 資產(chǎn)包。把資源管理工作自動(dòng)化之后反而要重新審視哪些資源該交給自動(dòng)化管。自動(dòng)化處理的是穩(wěn)定、可預(yù)期的資源動(dòng)態(tài)性強(qiáng)的資源交給運(yùn)行時(shí)機(jī)制更合適。這個(gè)邊界想清楚gator 在鴻蒙工程里才能成為一個(gè)安心依賴的基礎(chǔ)設(shè)施而不是給你制造新的歷史包袱。從我這次完整遷移的經(jīng)驗(yàn)看gator 本身不需要什么驚心動(dòng)魄的鴻蒙原生適配真正的工作量在于把資源目錄規(guī)范、命名約定、CI 流程重新梳理一遍。但這部分投入的回報(bào)是實(shí)打?qū)嵉默F(xiàn)在團(tuán)隊(duì)里新同事接手資源相關(guān)需求不再需要翻著字符串猜路徑編輯器點(diǎn)兩下就能看到全部可用資源。鴻蒙側(cè)打包的驗(yàn)證鏈路也清爽了很多資源目錄的變更從容易出事的手工操作變成了有索引可查、有編譯期保障的常規(guī)改動(dòng)。如果你也在做 Flutter 的鴻蒙化適配資源體系這塊建議早點(diǎn)動(dòng)手越晚遷移歷史資源的坑就越多。