"Flutter"
- T.C1 WebSocket text/binary frame 被 FakeWebSocketChannel 遮蔽
Flutter app 用 Uint8List 發送 WS 資料走 binary frame,ttyd 期望 text frame 靜默忽略 — FakeWebSocketChannel 的 sink.add 接受 dynamic 不區分 frame type,192 個 test 全過但實機無回應
- U.C1 Terminal 畫面五個狀態零個退出路徑
Flutter app 的 Terminal 畫面有 idle/connecting/connected/error/disconnected 五個 enum 狀態,每個狀態都沒有 back 或 disconnect 按鈕 — 使用者一旦進入就出不去
- Widget test 的狀態覆蓋策略
從畫面狀態矩陣推導 widget test case — 每個狀態的顯示、操作、退出路徑都是獨立的斷言目標
- Flutter GoRouter 導航設計
GoRouter 的路由定義、導航 API(go / push / pushReplacement)、redirect 機制和 ShellRoute 的使用場景
- Flutter 平台適配
Isolate 安全、Platform channel 攔截、app lifecycle 事件 — Flutter SDK 的平台特殊考量
- U.C2 biometricOnly=true 無密碼 fallback
Flutter app 的生物辨識設定 biometricOnly: true 阻擋所有非生物辨識認證方式 — Face ID 不可用時使用者直接被擋住,沒有替代路徑
- 導航路徑 test
Back 按鈕、route 可達性、go vs push 語意 — 驗證使用者能從任何畫面回到預期的位置
- U.C3 終端機文字輸入機制未設計、事後 hotfix 補 TextField
Flutter 終端機 app 的鍵盤輸入完全未設計 — 沒有 TextField、沒有 keyboard type 選擇、沒有 IME 控制。W2 修復時才補上 TextField + 6 個參數(enableSuggestions/autocorrect/enableIMEPersonalizedLearning/keyboardType/textInputAction/onSubmitted),全是散落 hotfix
- T.C4 Client-side log 缺失導致 debug 只能靠實機盲測
Flutter app 六個核心元件中只有兩個有 log(且全是 W2 hotfix 補的),連線失敗時開發者無法從任何 log 判斷失敗發生在哪一步 — 被迫用最昂貴的 debug 方式:插拔裝置反覆測試
- U.C4 首頁缺配對入口按鈕、導航流未完整列出
Flutter app 首頁只有 Connect Terminal 按鈕、沒有 Enroll Device 入口 — 使用者首次使用時找不到配對功能。根因是導航流設計只考慮了日常操作(UC-02 連線)、遺漏了首次操作(UC-01 配對)的入口
- go vs push vs pushReplacement 的 UX 語意表
三種導航方法對堆疊、back 行為、使用者心理模型的影響 — 選擇依據是使用者的意圖而非技術方便
- Widget 子類重新宣告 key — 遮蔽父類屬性與 duplicate key 風險
在 StatelessWidget 子類中重新宣告 final Key? key,會遮蔽 Widget 繼承的 key 屬性,產生兩份儲存槽。若再把同一個 key 往下傳給 child widget,同一棵子樹出現重複 key,rebuild 時 Flutter 可能拋錯。
- 192 個測試全過、實機全壞:Mock 遮蔽真實行為的三層測試策略
unit test 全綠、實機部署後功能整片壞掉。mock-only 策略的結構盲區(text vs binary frame、缺 auth handshake、ANSI 多樣性被 FakeWebSocketChannel 遮蔽),以及分層測試各抓什麼、各遮蔽什麼。
- 每個畫面都需要出口:畫面狀態機設計與 UX 導航的系統性方法
實機測到某畫面沒有返回或退出按鈕、使用者被困住。根因是企劃沒系統列出每個畫面的狀態與可用操作;用畫面狀態矩陣確保每個狀態都有明確出口。
- 為什麼這個場景適合用高階函式?以 Flutter 設定更新為例,比較 typedef 改寫前後
高階函式的適用判準(流程固定、變化點單一且開放)與裸函式型別 vs typedef 的可讀性取捨並排比較。
- 寫測試時 sync try-catch 接不到 BotToast 的 async 錯誤:fire-and-forget API 的接管設計
測試裡 sync try-catch 接不到錯誤,或 fire-and-forget API 從 async gap 後拋 `LateInitializationError`。用 runZonedGuarded 同時罩 sync 與 async 失敗路徑,含 fallback 訊息 signature 設計。
- flutter devices 卡住的訊號:device 數從 N 變 N-1 與 emulator 半活
`flutter devices` / `flutter run` 卡住又印 `Error -2 retrieving device properties` 時回來看。根因是 Android emulator 半活狀態,附恢復順序。
- Freezed 的三層結構解剖:with、_$、以及更好懂的替代路徑
freezed `class X with _$X implements Y` 的分層結構解剖:`with` 與 `_$` 各自的角色、沒有 freezed 怎麼手做、中間投影物件 vs DTO 直接 implements 的維護取捨。
- Dart test 的跨檔案 GetX 狀態污染:flaky 真因不是 fail 訊息上的那個 test
`flutter test` 整套跑隨機 fail、單獨跑該 file 卻 100% 過。根因是 dart test runner 同 process 內 GetX state 跨 file 污染,fail 位置看 `+N -1` 累計而非訊息標示的 test。
- Dart StreamController:single-subscription vs broadcast 的設計選型問題
Dart `Bad state: Stream has already been listened to.` 的根因:預設單訂閱在第二個訂閱者出現時才爆。StreamController vs .broadcast() 修復決策、與 Rx / .obs 的比較。
- Gradle JVM target 除錯復盤:七個節點的策略權衡
Gradle JVM target 不一致的除錯決策復盤,重點在每步的策略權衡與走過的彎路。
- Gradle 強制覆寫 plugin 的 JVM target:Kotlin 與 Java 的切入點不對稱
Kotlin / AGP 升級後 build 報 `Inconsistent JVM-target compatibility`。為何要強制覆寫 plugin 的 JVM target,以及 Kotlin 與 Java 設定切入點的不對稱。
- 為什麼 Bug 在合併後才爆:Gradle Cache 掩蓋潛伏問題的邏輯
feature branch build 正常、合併到 main 後才爆、但合併前 main 也沒錯。根因早已潛伏,Gradle cache 掩蓋、合併只是觸發條件。
- Flutter HitTestBehavior:控制點擊命中測試的三種模式
GestureDetector 點空白 padding 區沒反應、或點擊穿透/阻擋行為不符預期。HitTestBehavior 各模式(deferToChild / opaque / translucent)的命中規則與適用場景。
- Freezed 選型評估
Dart 專案是否引入 freezed 的選型評估:原型階段選 json_serializable + Equatable 取代 freezed 的理由與優缺點對照。
- 系統化除錯方法論
警告修復標準化流程
- flutter 可以使用的 togglebutton 樣式
Flutter 切換選項按鈕的元件選型。並列 ToggleButtons 等可用樣式的外觀截圖與程式碼。