移除 nullOk 參數
摘要
#本遷移指南說明如何將使用多個 of 靜態存取器及相關存取器上的 nullOk 參數的程式碼,轉換為使用回傳可為 null 的替代 API。
背景
#Flutter 常見的一種模式,是允許透過靜態成員函式來查找某些類型的元件(InheritedWidgets),這些函式通常命名為 of,並接受一個 BuildContext。
在 non-nullability(非空安全)尚未成為預設之前,這些 API 提供一個切換開關,能夠在元件樹中找不到該元件時,選擇是拋出例外還是回傳 null。這樣的設計很實用,也不會造成混淆,因為當時每個變數都可以是 nullable。
當 non-nullability 成為預設後,讓最常用的 API 回傳 non-nullable 值就變得更理想。因為如果呼叫 MediaQuery.of(context, nullOk: false) 後,仍然需要加上 ! 運算子,或是 ? 並加上預設值,這樣的寫法顯得不自然。
nullOk 參數原本是一種簡便的 null safety 切換方式,但隨著語言本身支援 non-nullability,這個參數就變得多餘,甚至可能給開發者帶來矛盾的訊息。
為了解決這個問題,of 存取器(以及其他也使用 nullOk 的相關存取器)被拆分為兩種呼叫方式:一種回傳 non-nullable 值,若找不到目標元件則拋出例外;另一種則回傳可為 null 的值,不會拋出例外,找不到元件時回傳 null。
本變更的設計文件請參考 Eliminating nullOk parameters。
變更說明
#實際的變更是將這些 API 移除 nullOk 參數,並改為回傳 non-nullable 值:
MediaQuery.ofNavigator.ofScaffoldMessenger.ofScaffold.ofRouter.ofLocalizations.localeOfFocusTraversalOrder.ofFocusTraversalGroup.ofFocus.ofShortcuts.ofActions.handlerActions.findActions.invokeAnimatedList.ofSliverAnimatedList.ofCupertinoDynamicColor.resolveCupertinoDynamicColor.resolveFromCupertinoUserInterfaceLevel.ofCupertinoTheme.brightnessOfCupertinoThemeData.resolveFromNoDefaultCupertinoThemeData.resolveFromCupertinoTextThemeData.resolveFromMaterialBasedCupertinoThemeData.resolveFrom
並同時新增以下這些 API,讓其回傳可為 null 的值:
MediaQuery.maybeOfNavigator.maybeOfScaffoldMessenger.maybeOfScaffold.maybeOfRouter.maybeOfLocalizations.maybeLocaleOfFocusTraversalOrder.maybeOfFocusTraversalGroup.maybeOfFocus.maybeOfShortcuts.maybeOfActions.maybeFindActions.maybeInvokeAnimatedList.maybeOfSliverAnimatedList.maybeOfCupertinoDynamicColor.maybeResolveCupertinoUserInterfaceLevel.maybeOfCupertinoTheme.maybeBrightnessOf
遷移指南
#為了讓你的程式碼改用新的 API 形式,請將所有帶有 nullOk = true 參數的呼叫,改為使用 maybe 形式的 API。
也就是說,原本這樣的寫法:
MediaQueryData? data = MediaQuery.of(context, nullOk: true);變更為:
MediaQueryData? data = MediaQuery.maybeOf(context);你也需要修改所有使用 nullOk = false(通常為預設值)呼叫 API 的情境,以接受不可為 null 的回傳值,或移除任何 ! 運算子:
所以可以選擇以下任一方式:
MediaQueryData data = MediaQuery.of(context)!; // nullOk false by default.
MediaQueryData? data = MediaQuery.of(context); // nullOk false by default.兩者都變成:
MediaQueryData data = MediaQuery.of(context); // No ! or ? operator here now.unnecessary_non_null_assertion 分析選項在尋找應移除 ! 運算子的地方時非常有幫助,而 unnecessary_nullable_for_final_variable_declarations 分析選項則有助於找出在 final 和 const 變數上不必要的問號運算子。
時程表
#合併於版本:1.24.0
正式版釋出:2.0.0
參考資料
#API 文件:
MediaQuery.ofNavigator.ofScaffoldMessenger.ofScaffold.ofRouter.ofLocalizations.localeOfFocusTraversalOrder.ofFocusTraversalGroup.ofFocus.ofShortcuts.ofActions.handlerActions.findActions.invokeAnimatedList.ofSliverAnimatedList.ofCupertinoDynamicColor.resolveCupertinoDynamicColor.resolveFromCupertinoUserInterfaceLevel.ofCupertinoTheme.brightnessOfCupertinoThemeData.resolveFromNoDefaultCupertinoThemeData.resolveFromCupertinoTextThemeData.resolveFromMaterialBasedCupertinoThemeData.resolveFromMediaQuery.maybeOfNavigator.maybeOfScaffoldMessenger.maybeOfScaffold.maybeOfRouter.maybeOfLocalizations.maybeLocaleOfFocusTraversalOrder.maybeOfFocusTraversalGroup.maybeOfFocus.maybeOfShortcuts.maybeOfActions.maybeFindActions.maybeInvokeAnimatedList.maybeOfSliverAnimatedList.maybeOfCupertinoDynamicColor.maybeResolveCupertinoUserInterfaceLevel.maybeOfCupertinoTheme.maybeBrightnessOf
相關議題:
相關 PR:
- Remove
nullOkinMediaQuery.of - Remove
nullOkinNavigator.of - Remove
nullOkparameter fromAnimatedList.ofandSliverAnimatedList.of - Remove
nullOkparameter fromShortcuts.of,Actions.find, andActions.handler - Remove
nullOkparameter fromFocus.of,FocusTraversalOrder.of, andFocusTraversalGroup.of - Remove
nullOkparameter fromLocalizations.localeOf - Remove
nullOkparameter fromRouter.of - Remove
nullOkfromScaffold.ofandScaffoldMessenger.of - Remove
nullOkparameter from Cupertino color resolution APIs - Remove vestigial
nullOkparameter fromLocalizations.localeOf - Remove
nullOkfromActions.invoke, addActions.maybeInvoke