-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Throw StateError when implicitView is null on wrapWithDefaultView
.
#155734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw StateError when implicitView is null on wrapWithDefaultView
.
#155734
Conversation
This allows us to render a more user-friendly error, instead of failing with an "unexpected null value" a few lines below.
@@ -1229,6 +1229,12 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB | |||
/// The `rootWidget` widget provided to this method must not already be | |||
/// wrapped in a [View]. | |||
Widget wrapWithDefaultView(Widget rootWidget) { | |||
assert( | |||
platformDispatcher.implicitView != null, | |||
'The implicitView is null. Cannot create a default View from `runApp`. ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error uses jargon that most Flutter developers won't know. This might frustrate users.
Perhaps we should add more context? Maybe something like:
runApp
requires an implicit view.
runApp
renders the widget tree into a view provided by the platform,
called the "implicit view". However, the platform did not provide an
implicit view.Try using
runWidget
instead ofrunApp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's a public API, I think we should not assume it 100% comes from runApp
. Maybe
The app requested an implicit view, but the platform doesn't have one.
This is likely because the app called
runApp
to start up, which expects the platform to provide a default view to render into ("the implicit view"), while the engine has multi-view mode enabled, which requires the app handle view creation.Try using
runWidget
instead ofrunApp
. See also https://flutter.dev/to/web-runwidget
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@loic-sharma @dkwingsmt I ended up with something like this, I hope it makes more sense!
The app is attempting to render into a default View that isn't available (
platformDispatcher.implicitView == null
).
This is likely because the platform has multi-view mode enabled, but the app is callingrunApp
to render its root Widget.
Try usingrunWidget
instead ofrunApp
to start your app.runWidget
allows you to provide aView
widget, without requiring a default on the platform.
See: https://flutter.dev/to/web-multiview-runwidget
(Tried to use lingo closer to that in the wrapWithDefaultView method docs.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I slightly prefer Tong's wording.
Some context:
- On desktop, the north star is that the app will call
runApp
even though there's no implicit view.runApp
will know how to create a window to host the widget tree. - On desktop, you can have multiple views while also having an implicit view. Thus, on desktop you can call
runApp
even if you have multi-view mode enabled
Since it's a public API, I think we should not assume it 100% comes from runApp.
Should we move this error to runApp
then and then make wrapWithDefaultView
assert that platformDispatcher.implicitView != null
?
What do y'all think about this? I tried to merge bits from all our messages :)
The app requested an implicit view, but the platform did not provide one.
runApp
expects the platform to provide a default view to render into ("the implicit view").
However, the platform did not provide a default "implicit" view, likely because it has multi-view mode enabled.Try using
runWidget
instead ofrunApp
to start your app.runWidget
allows you to provide aView
widget, without requiring a default view.
See: https://flutter.dev/to/web-multiview-runwidget
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
I think checking it in wrapWithDefaultView is better than runApp since wrapWithDefaultView is also a public API and users can still call it incorrectly (which is a user error and you shouldn't assert on).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied @loic-sharma's suggestion! If @dkwingsmt is happy, I'm happy too, let's autosubmit
this :P
(Off-topic)
runApp
will know how to create a window to host the widget tree.
...
you can have multiple views while also having an implicit view
We need to discuss this elsewhere, I'm interested :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with nits.
I'm not familiar with multiview so I'm happy to defer to anyone else that might be, but I know @goderbauer is out for awhile. This looks good from my perspective though. Using throwsA
to check the assertion seems fine.
Also it looks like there are failures.
We're adding a more descriptive error when a misconfigured multi-view web app attempts to run (flutter/flutter#155734), and we want a permalink to the relevant bit of the docs. This PR adds a `/to/web-multiview-runwidget` redirect, pointing to the correct part of the docs.
## Description We're adding a more descriptive error when a misconfigured multi-view web app attempts to run (flutter/flutter#155734), and we want a permalink to the relevant bit of the docs. This PR adds a `/to/web-multiview-runwidget` redirect, pointing to the correct part of the docs. ## Issues Needed for flutter/flutter#155734 ## Presubmit checklist - [ ] This PR is marked as draft with an explanation if not meant to land until a future stable release. - [x] This PR doesn’t contain automatically generated corrections (Grammarly or similar). - [x] This PR follows the [Google Developer Documentation Style Guidelines](https://developers.google.com/style) — for example, it doesn’t use _i.e._ or _e.g._, and it avoids _I_ and _we_ (first person). - [ ] This PR uses [semantic line breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks) of 80 characters or fewer.
implicitView != null
on wrapWithDefaultView
.wrapWithDefaultView
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error message looks good to me, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Manual roll requested by stuartmorgan@google.com flutter/flutter@fa402c8...ead6b0d 2024-09-27 kustermann@google.com Remove left-over traces of "link-dry-run" - which isn't used anywhere in flutter (flutter/flutter#155820) 2024-09-27 engine-flutter-autoroll@skia.org Roll Flutter Engine from e57b440ec4ee to 7c603de2dca7 (5 revisions) (flutter/flutter#155811) 2024-09-27 bruno.leroux@gmail.com Fix DropdownMenu rendered behind AppBar (flutter/flutter#155539) 2024-09-27 engine-flutter-autoroll@skia.org Roll Flutter Engine from 53517772a5b0 to e57b440ec4ee (8 revisions) (flutter/flutter#155799) 2024-09-27 ditman@gmail.com Throw StateError when implicitView is null on `wrapWithDefaultView`. (flutter/flutter#155734) 2024-09-27 34871572+gmackall@users.noreply.github.com Roll packages manually (flutter/flutter#155786) 2024-09-27 rmolivares@renzo-olivares.dev fix: SelectableText should handle focus changes (flutter/flutter#155771) 2024-09-27 34871572+gmackall@users.noreply.github.com Use flutter from in same repo (not path) in `generate_gradle_lockfiles.dart` (again) (flutter/flutter#155794) 2024-09-26 34871572+gmackall@users.noreply.github.com Use flutter from in same repo (not path) in `generate_gradle_lockfiles.dart` (flutter/flutter#155790) 2024-09-26 rmolivares@renzo-olivares.dev `RenderParagraph` should invalidate its `_SelectableFragment`s cached rects on window size updates (flutter/flutter#155719) 2024-09-26 zeqinjie@qq.com Fix broken text field with set hint and min and max lines(#153183) (flutter/flutter#153235) 2024-09-26 engine-flutter-autoroll@skia.org Roll Flutter Engine from 9e6133e8d906 to 53517772a5b0 (1 revision) (flutter/flutter#155772) 2024-09-26 ian@hixie.ch Fix line-wrapping in `flutter create` error message. (flutter/flutter#150325) 2024-09-26 christopherfujino@gmail.com remove fujino from CODEOWNERS (flutter/flutter#155369) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC camillesimon@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This PR tweaks
wrapWithDefaultView
(used byrunApp
) to raise a StateError with a legible error message when theplatformDispatcher.implicitView
is missing (for example, when enabling multi-view embedding on the web), instead of crashing with an unexpectednullCheck
a few lines below.Before:

After:

Issues
Unexpected null value
error appears when running multiView on Flutter Web #153198Tests
Added a test to ensure the assertion is thrown when the
implicitView
is missing. Had to hack a little because I couldn't find any clean way of overriding theimplicitView
. The problem is that the flutter_test bindings userunApp
internally a couple of times, so I can only disable the implicitView inside the test body (and must re-enable it before returning). Not sure if it's the best way, but it seems to do the trick for this simple test case!Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.