Eliminating nullOk Parameters
Summary
#This migration guide describes conversion of code that uses the nullOk
parameter on multiple of
static accessors and related accessors to use alternate APIs with nullable return values.
Context
#Flutter has a common pattern of allowing lookup of some types of widgets (InheritedWidget
s) using static member functions that are typically called of
, and take a BuildContext
.
Before non-nullability was the default, it was useful to have a toggle on these APIs that swapped between throwing an exception if the widget was not present in the widget tree and returning null if it was not found. It was useful, and wasn't confusing, since every variable was nullable.
When non-nullability was made the default, it was then desirable to have the most commonly used APIs return a non-nullable value. This is because saying MediaQuery.of(context, nullOk: false)
and then still requiring an !
operator or ?
and a fallback value after that call felt awkward.
The nullOk
parameter was a cheap form of providing a null safety toggle, which in the face of true language support for non-nullability, was then supplying redundant, and perhaps contradictory signals to the developer.
To solve this, the of
accessors (and some related accessors that also used nullOk
) were split into two calls: one that returned a non-nullable value and threw an exception when the sought-after widget was not present, and one that returned a nullable value that didn't throw an exception, and returned null if the widget was not present.
The design document for this change is Eliminating nullOk parameters.
Description of change
#The actual change modified these APIs to not have a nullOk
parameter, and to return a non-nullable value:
MediaQuery.of
Navigator.of
ScaffoldMessenger.of
Scaffold.of
Router.of
Localizations.localeOf
FocusTraversalOrder.of
FocusTraversalGroup.of
Focus.of
Shortcuts.of
Actions.handler
Actions.find
Actions.invoke
AnimatedList.of
SliverAnimatedList.of
CupertinoDynamicColor.resolve
CupertinoDynamicColor.resolveFrom
CupertinoUserInterfaceLevel.of
CupertinoTheme.brightnessOf
CupertinoThemeData.resolveFrom
NoDefaultCupertinoThemeData.resolveFrom
CupertinoTextThemeData.resolveFrom
MaterialBasedCupertinoThemeData.resolveFrom
And introduced these new APIs alongside those, to return a nullable value:
MediaQuery.maybeOf
Navigator.maybeOf
ScaffoldMessenger.maybeOf
Scaffold.maybeOf
Router.maybeOf
Localizations.maybeLocaleOf
FocusTraversalOrder.maybeOf
FocusTraversalGroup.maybeOf
Focus.maybeOf
Shortcuts.maybeOf
Actions.maybeFind
Actions.maybeInvoke
AnimatedList.maybeOf
SliverAnimatedList.maybeOf
CupertinoDynamicColor.maybeResolve
CupertinoUserInterfaceLevel.maybeOf
CupertinoTheme.maybeBrightnessOf
Migration guide
#In order to modify your code to use the new form of the APIs, convert all instances of calls that include nullOk = true
as a parameter to use the maybe
form of the API instead.
So this:
MediaQueryData? data = MediaQuery.of(context, nullOk: true);
becomes:
MediaQueryData? data = MediaQuery.maybeOf(context);
You also need to modify all instances of calling the API with nullOk = false
(often the default), to accept non-nullable return values, or remove any !
operators:
So either of:
MediaQueryData data = MediaQuery.of(context)!; // nullOk false by default.
MediaQueryData? data = MediaQuery.of(context); // nullOk false by default.
both become:
MediaQueryData data = MediaQuery.of(context); // No ! or ? operator here now.
The unnecessary_non_null_assertion
analysis option can be quite helpful in finding the places where the !
operator should be removed, and the unnecessary_nullable_for_final_variable_declarations
analysis option can be helpful in finding unnecessary question mark operators on final
and const
variables.
Timeline
#Landed in version: 1.24.0
In stable release: 2.0.0
References
#API documentation:
MediaQuery.of
Navigator.of
ScaffoldMessenger.of
Scaffold.of
Router.of
Localizations.localeOf
FocusTraversalOrder.of
FocusTraversalGroup.of
Focus.of
Shortcuts.of
Actions.handler
Actions.find
Actions.invoke
AnimatedList.of
SliverAnimatedList.of
CupertinoDynamicColor.resolve
CupertinoDynamicColor.resolveFrom
CupertinoUserInterfaceLevel.of
CupertinoTheme.brightnessOf
CupertinoThemeData.resolveFrom
NoDefaultCupertinoThemeData.resolveFrom
CupertinoTextThemeData.resolveFrom
MaterialBasedCupertinoThemeData.resolveFrom
MediaQuery.maybeOf
Navigator.maybeOf
ScaffoldMessenger.maybeOf
Scaffold.maybeOf
Router.maybeOf
Localizations.maybeLocaleOf
FocusTraversalOrder.maybeOf
FocusTraversalGroup.maybeOf
Focus.maybeOf
Shortcuts.maybeOf
Actions.maybeFind
Actions.maybeInvoke
AnimatedList.maybeOf
SliverAnimatedList.maybeOf
CupertinoDynamicColor.maybeResolve
CupertinoUserInterfaceLevel.maybeOf
CupertinoTheme.maybeBrightnessOf
Relevant issue:
Relevant PRs:
- Remove
nullOk
inMediaQuery.of
- Remove
nullOk
inNavigator.of
- Remove
nullOk
parameter fromAnimatedList.of
andSliverAnimatedList.of
- Remove
nullOk
parameter fromShortcuts.of
,Actions.find
, andActions.handler
- Remove
nullOk
parameter fromFocus.of
,FocusTraversalOrder.of
, andFocusTraversalGroup.of
- Remove
nullOk
parameter fromLocalizations.localeOf
- Remove
nullOk
parameter fromRouter.of
- Remove
nullOk
fromScaffold.of
andScaffoldMessenger.of
- Remove
nullOk
parameter from Cupertino color resolution APIs - Remove vestigial
nullOk
parameter fromLocalizations.localeOf
- Remove
nullOk
fromActions.invoke
, addActions.maybeInvoke
Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2024-04-04. View source or report an issue.