Migrate `of` to non-nullable return values, and add `maybeOf`
Summary
This migration guide describes conversion of code that uses various static of
functions to retrieve information from a context that used to return nullable
values, but now return non-nullable values.
Context
Flutter has a common pattern of allowing lookup of some types of widgets
(typically InheritedWidget
s, but also others) using static member
functions that are typically called of
.
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
Scrollable.of(context)
and then still requiring an !
operator or ?
and a
fallback value after that call felt awkward, and was not idiomatic for
non-nullable Dart code.
A lot of this migration was performed when we eliminated nullOk
parameters in
a previous migration, but some of
methods were missed in that migration,
and some were subsequently added with nullable return types, counter to our
common pattern.
In this migration, the affected of
accessors were split into two calls: one
that returned a non-nullable value and threw an exception when the sought-after
value was not present (still called of
), and one that returned a nullable
value that didn’t throw an exception, and returned null if the value was not
present (a new method called maybeOf
).
Description of change
The change modified these static of
APIs to return non-nullable values. If a
value is not found, they will also now assert in debug mode, and throw an
exception in release mode.
AutofillGroup.of
DefaultTabController.of
DefaultTextHeightBehavior.of
Form.of
HeroControllerScope.of
Material.of
Overlay.of
PageStorage.of
PrimaryScrollController.of
RenderAbstractViewport.of
RestorationScope.of
Scrollable.of
ScrollNotificationObserver.of
This change also introduced new static maybeOf
APIs alongside the above functions,
which return a nullable version of the same value, and simply return null if the
value is not found, without throwing any exceptions.
AutofillGroup.maybeOf
DefaultTabController.maybeOf
DefaultTextHeightBehavior.maybeOf
Form.maybeOf
HeroControllerScope.maybeOf
Material.maybeOf
Overlay.maybeOf
PageStorage.maybeOf
PrimaryScrollController.maybeOf
RenderAbstractViewport.maybeOf
RestorationScope.maybeOf
Scrollable.maybeOf
ScrollNotificationObserver.maybeOf
Migration guide
To modify your code to use the new form of the APIs, first convert all
instances of the original static of
functions (where its nullability is
important) to use the maybeOf
form instead.
Code before migration:
ScrollController? controller = Scrollable.of(context);
Code after migration:
ScrollController? controller = Scrollable.maybeOf(context);
Then, for instances where the code calls the of
API followed by an exclamation
point, just remove the exclamation point: it can no longer return a nullable
value.
Code before migration:
ScrollController controller = Scrollable.of(context)!;
Code after migration:
ScrollController controller = Scrollable.of(context);
The following can also be helpful:
-
unnecessary_non_null_assertion
(linter message) identifies places where an!
operator should be removed -
unnecessary_null_checks
(analysis option) identifies places where the?
operator isn’t needed -
unnecessary_null_in_if_null_operators
identifies places where a??
operator isn’t needed -
unnecessary_nullable_for_final_variable_declarations
(analysis option) finds unnecessary question mark operators onfinal
andconst
variables
Timeline
In stable release: 3.7
References
API documentation:
Relevant PRs: