🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

======================================

「能正常跑的程式碼就盡量不要動」,這句話再一次證明了它的立場,實際上確實不少程式設計師都有「程式碼潔癖」,喜歡對程式碼進行「清洗」和「重構」,但優雅的背後,很多時候也伴隨著看不見的坑在等著你。

你以為上一代的人為什麼就偏要寫得「那麼蠢」?

回到正題,近日不少人在 #180842 中反饋,當 Flutter 升級後,點擊帶有 AutoFill 的輸入框時,鍵盤會像「抽風」一樣先彈起、收縮、再彈起:

這個乍看似乎沒什麼問題,但如果在 Flutter 3.38.7 的版本裡,它的表現是這樣的:

這麼一對比就可以很直觀看出來,這是一個負優化,特別是對於剛升級的使用者來說,這就顯得很莫名其妙:

而從目前的情況來看,問題的來源是以下這個 PR ,它是用來修復 autofill 上下文清理的提交,在這個 commit 裡,對 FlutterTextInputPlugin.mm 進行了重構,主要是簡化輸入視圖的生命週期管理:

但是在這個過程裡,它修改了 removeFromSuperview 的呼叫時機,看起來合理,是在清理無用 view,但問題在於呼叫順序:

在多輸入框切換(A → B)時,Flutter 平台端的呼叫順序通常是:

TextInput.clearClient (A)
TextInput.setClient   (B)

也就是說:

  • 舊欄位先被 clear
  • 緊接著新欄位被 set

但是如果在 clear 階段就把承載輸入的 _activeView 從 view hierarchy 裡 remove,那麼

  • iOS 會認為「輸入上下文結束」
  • 系統可能觸發鍵盤 dismiss 和高度重算
  • 下一幀新欄位 becomeFirstResponder
  • 鍵盤又被彈起

對比 3.38 時,當時採用的是「懶惰清理」策略,即使輸入 client 關閉,底層的原生視圖(activeView)依然掛載在視圖樹上。

而 3.41 一旦 clearTextInputClient 被呼叫,就會立即執行 removeFromSuperview,因為:

  • 在 iOS 上,當系統偵測到輸入框支援自動填入(AutoFill)時,它會發送兩次鍵盤顯示通知,第一次是普通高度,第二次是加上「自動填入工具列」後的高度
  • 而在 iOS 準備計算第二次高度、彈出工具列的微秒時間內,Flutter 執行了「清理邏輯」,強行把焦點所在的 activeView 刪除了
  • iOS 發現「焦點視圖沒了」,於是鍵盤收起;緊接著,Flutter 的下一步邏輯又啟用新視圖,鍵盤再次彈起

而這個情況,在 iOS 18+ 之後的輸入堆疊 + AutoFill / 密碼建議 UI 更敏感:

  • 登入/密碼情境下,系統會在鍵盤上方插入建議列
  • 鍵盤 frame / safe area 會更頻繁變化
  • 中間態更容易被放大成視覺抖動

實際上上述的修改,如果不是事後看會覺得有問題,在體驗與邏輯上,當下可能都不覺得有什麼問題。

而這就是導致鍵盤在螢幕內上下閃動的原因,實際上類似問題在 React Native 上也曾出現過:

因為無論是 Flutter 或 RN,它們都不是「原生即時渲染」,而是透過一個中間層與 iOS 通訊,所以上述的 RN 也有過類似的鍵盤高度計算等問題,不過 RN 上主要是 AutoFill UI + layout 的競態導致的問題。

而針對這個問題,造成問題的原作者也提交了新的修復 PR #182661,在 FlutterTextInputPlugin.mm 引入了全新狀態,不再直接 removeFromSuperview,而是標記一個 _pendingInputViewRemoval = YES

PR 的目的是將真正的移除動作放到 hideTextInput 階段,也就是確保 resignFirstResponder 已經完成,從而對齊原本的系統節奏。

可以看到,這原本也不算是什麼大改動,出發點也是良善的,但這種細節的邊界情況,往往也是造成大問題的導火線,這種 Bug 對使用者來說,雖然不影響實際功能,但在體驗上確實是致命缺陷。

所以很多時候,你可能會想為什麼一些簡單的修改,Flutter 花很久才合併或提交,這就是一個典型例子,誰能保證 feature 有被完整回歸?說人話就是:我要不要為這東西的未來背鍋?

所以,每個歷史遺留的爛程式碼,大多都有它存在的理由,單純因為爛就把它砍掉的也有,但更多時候,大家還是傾向在爛上雕花,除非這坨當初就是自己拉的,你還知道它臭在哪裡。


原文出處:https://juejin.cn/post/7615894702423900223


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝23   💬8   ❤️1
581
🥈
我愛JS
📝1   💬6  
36
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付