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 issues:
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