點擊導(dǎo)致重復(fù)提交如何做冪等)
HarmonyOS 7.0 API26 互動卡片代碼封裝桌面卡片連續(xù)點擊導(dǎo)致重復(fù)提交如何做冪等這篇只拆一個具體點互動卡片。版本邊界先放前面下面的寫法面向 HarmonyOS 7.0 / API 26。工程里如果還在混用舊 SDK、舊模擬器鏡像或舊設(shè)備系統(tǒng)先不要直接照搬代碼先把版本對齊。這個問題為什么值得單獨拆開發(fā)者真正會踩坑的地方不是接口名記不住而是版本、設(shè)備形態(tài)、資源狀態(tài)和頁面生命周期湊到一起以后問題才出現(xiàn)。以 互動卡片 為例桌面卡片連續(xù)點擊導(dǎo)致重復(fù)提交如何做冪等。如果只看單次點擊很難發(fā)現(xiàn)必須把觸發(fā)條件、失敗日志和兜底路徑一起設(shè)計。這類問題的麻煩點是代碼經(jīng)常能編譯頁面第一次打開也像是正常的但一到折疊屏、多窗口、后臺恢復(fù)、跨設(shè)備入口或?qū)徍藱C(jī)型上行為就開始不穩(wěn)定。我的處理方式不是先改 UI而是先把能力邊界、觸發(fā)條件、失敗原因和兜底方案拆開。先對齊官方能力邊界參考點要確認(rèn)什么落到代碼里怎么處理HarmonyOS 7.0 / API 26 官方能力說明確認(rèn)版本邊界和設(shè)備支持范圍先做能力判斷再進(jìn)入新能力分支ArkUI / ArkTS API 參考確認(rèn)組件生命周期、參數(shù)和異常返回把調(diào)用收口到 policy 或 guard不散落在頁面里應(yīng)用質(zhì)量與上架審核建議確認(rèn)權(quán)限、兼容和異常兜底把失敗原因?qū)戇M(jìn)日志和自測清單這里要避免一個常見誤區(qū)看到 7.0 新能力就直接在頁面里調(diào)用。更穩(wěn)的做法是先做一層能力判斷判斷通過再進(jìn)入新能力分支判斷失敗就明確走兜底日志里也要能看出失敗原因。兩個容易復(fù)現(xiàn)的案例案例一桌面卡片連續(xù)點擊導(dǎo)致重復(fù)提交如何做冪等復(fù)現(xiàn)方式不要做得太復(fù)雜。先把頁面打開到目標(biāo)狀態(tài)再連續(xù)觸發(fā)兩次能力入口。這個時候重點看三個點狀態(tài)有沒有丟、資源有沒有重復(fù)申請、失敗時有沒有明確原因。案例二卡片跨設(shè)備刷新延遲如何給出可見狀態(tài)第二個場景更接近線上用戶不會按開發(fā)者預(yù)設(shè)路徑操作他會切后臺、恢復(fù)、換方向、分屏、拖拽、鎖屏再回來。只看單次點擊問題很容易被遮住。拆法先決策再執(zhí)行再兜底我會把實現(xiàn)拆成三層1. 能力判斷層只判斷版本、設(shè)備形態(tài)、入口參數(shù)和依賴狀態(tài)。2. 執(zhí)行層只負(fù)責(zé)調(diào)用具體 API不混入頁面展示邏輯。3. 兜底層能力不可用時給舊方案、提示或延遲重試不讓頁面進(jìn)入半壞狀態(tài)。這樣拆的好處是后面升級 SDK 或換設(shè)備時不需要在每個頁面里翻 if 判斷。頁面只拿一個明確結(jié)果能用、不能用、為什么不能用。Demo把能力判斷收口到一個 guardtype CapabilityStatus enable | fallback | blocked; interface CapabilityInput { apiLevel: number; deviceType: string; scene: string; resourceReady: boolean; } interface CapabilityDecision { status: CapabilityStatus; reason: string; nextAction: string; } class Api26CapabilityPolicy { decide(input: CapabilityInput): CapabilityDecision { if (input.apiLevel 26) { return { status: fallback, reason: api-level-below-26, nextAction: use-old-path }; } if (!input.deviceType || input.deviceType unknown) { return { status: blocked, reason: device-type-unknown, nextAction: collect-device-info }; } if (!input.resourceReady) { return { status: fallback, reason: resource-not-ready, nextAction: show-lightweight-ui }; } return { status: enable, reason: api26-ready, nextAction: 互動卡片-enabled }; } } Entry Component struct CapabilityDemoPage { State private result: string waiting; private policy: Api26CapabilityPolicy new Api26CapabilityPolicy(); private verify(): void { const decision this.policy.decide({ apiLevel: 26, deviceType: foldable, scene: main-entry, resourceReady: true }); this.result decision.status : decision.reason : decision.nextAction; console.info([api26-policy], this.result); } build() { Column({ space: 16 }) { Text(API 26 capability check).fontSize(20).fontWeight(FontWeight.Bold) Text(this.result).fontSize(16) Button(run verify).onClick(() this.verify()) }.width(100%).padding(20) } }這個 Demo 只做一件事先判斷能力條件再把結(jié)果交給頁面。頁面不直接關(guān)心 API 細(xì)節(jié)也不把版本判斷散落在 build 里。后面要接真實頁面時可以把 HarmonyFeatureGuard 放到公共模塊里復(fù)用。異常日志應(yīng)該長什么樣[feature-check] scenecapability, statusfailed, reasonapi-level-too-low [feature-check] scenecapability, statusfailed, reasondevice-mode-empty [feature-check] scenecapability, statuspassed, cost3ms日志不要只打印“失敗了”。至少要帶上 scene、status、reason 和耗時。否則出了問題以后只能靠猜。驗證矩陣場景輸入條件預(yù)期結(jié)果關(guān)鍵日志桌面卡片連續(xù)點擊導(dǎo)致重復(fù)提交如何做冪等API 26 支持設(shè)備進(jìn)入新能力分支statuspassed卡片跨設(shè)備刷新延遲如何給出可見狀態(tài)API 26 狀態(tài)恢復(fù)不重復(fù)申請資源reusetrue舊版本兼容檢查API 25 或能力缺失走兜底分支statusfailed, fallbacktrue異常輸入檢查設(shè)備形態(tài)未知或入口參數(shù)缺失給出可定位原因reason 非空跑完后應(yīng)該看到的結(jié)果case: api26_foldable_enable - passed case: api25_fallback - passed case: empty_device_mode - passed case: resume_without_duplicate_request - passed我會怎么選方案方案適合場景風(fēng)險繼續(xù)沿用舊寫法舊頁面、小范圍兼容遇到 7.0 新能力邊界時不好排查在頁面內(nèi)臨時處理快速驗證問題代碼容易散后面不好復(fù)用抽成獨立工具或組件多頁面、多設(shè)備、多狀態(tài)復(fù)用前期要把輸入輸出設(shè)計清楚我的選擇是第三種。只要這個能力會被多個頁面用到就不要把判斷邏輯塞在頁面里。頁面只負(fù)責(zé)展示能力邊界、異常兜底、版本判斷放到獨立函數(shù)或組件里。這樣后面改 SDK、換設(shè)備、補(bǔ)兼容邏輯影響面會小很多。排查順序1. 先看 SDK 和設(shè)備 API 版本不一致就不要繼續(xù)猜頁面代碼。2. 再看入口參數(shù)和設(shè)備形態(tài)很多問題不是 UI 寫錯而是能力條件根本不滿足。3. 再看日志里的失敗原因日志只打印 failed 沒有 reason后面一定會浪費時間。4. 最后再把能力判斷抽出去頁面只消費結(jié)果不直接散落版本判斷。可以怎么復(fù)用這個寫法可以繼續(xù)擴(kuò)成一個小工具輸入 featureName、apiLevel、deviceMode、entryState輸出 passed / failed / fallback 和 reason。頁面層只根據(jù)結(jié)果更新 UI。這樣做雖然前期多寫幾行代碼但后面接更多 HarmonyOS 7.0 能力時判斷邏輯不會越寫越散。最后總結(jié)這篇把 互動卡片 放到 HarmonyOS 7.0 / API 26 的版本邊界里分析用兩個場景說明問題怎么復(fù)現(xiàn)再用 guard、日志和驗證矩陣把處理方式固定下來。這類特性真正有價值的地方不是知道一個新名字而是知道它在什么場景該用、什么時候不該用、怎么復(fù)現(xiàn)問題、怎么把修復(fù)沉淀成可復(fù)用代碼。后面再接復(fù)雜頁面時先把這個小 Demo 跑通基本能避開一半低級返工。