Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
1e0007f3
Unverified
Commit
1e0007f3
authored
Oct 08, 2020
by
Michael Goderbauer
Committed by
GitHub
Oct 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement documented behavior of WidgetsApp.builder (#67574)
parent
cfc8ec23
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
77 additions
and
46 deletions
+77
-46
app.dart
packages/flutter/lib/src/widgets/app.dart
+66
-46
app_test.dart
packages/flutter/test/material/app_test.dart
+11
-0
No files found.
packages/flutter/lib/src/widgets/app.dart
View file @
1e0007f3
...
...
@@ -568,14 +568,15 @@ class WidgetsApp extends StatefulWidget {
final
List
<
NavigatorObserver
>?
navigatorObservers
;
/// {@template flutter.widgets.widgetsApp.builder}
/// A builder for inserting widgets above the [Navigator] but below the other
/// widgets created by the [WidgetsApp] widget, or for replacing the
/// [Navigator] entirely.
/// A builder for inserting widgets above the [Navigator] or - when the
/// [WidgetsApp.router] constructor is used - above the [Router] but below the
/// other widgets created by the [WidgetsApp] widget, or for replacing the
/// [Navigator]/[Router] entirely.
///
/// For example, from the [BuildContext] passed to this method, the
/// [Directionality], [Localizations], [DefaultTextStyle], [MediaQuery], etc,
/// are all available. They can also be overridden in a way that impacts all
/// the routes in the [Navigator].
/// the routes in the [Navigator]
or [Router]
.
///
/// This is rarely useful, but can be used in applications that wish to
/// override those defaults, e.g. to force the application into right-to-left
...
...
@@ -586,18 +587,22 @@ class WidgetsApp extends StatefulWidget {
/// [Localizations], consider [onGenerateTitle] instead.
///
/// The [builder] callback is passed two arguments, the [BuildContext] (as
/// `context`) and a [Navigator] widget (as `child`).
///
/// If no routes are provided using [home], [routes], [onGenerateRoute], or
/// [onUnknownRoute], the `child` will be null, and it is the responsibility
/// of the [builder] to provide the application's routing machinery.
///
/// If routes _are_ provided using one or more of those properties, then
/// `child` is not null, and the returned value should include the `child` in
/// the widget subtree; if it does not, then the application will have no
/// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute],
/// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will
/// have no effect.
/// `context`) and a [Navigator] or [Router] widget (as `child`).
///
/// If no routes are provided to the regular [WidgetsApp] constructor using
/// [home], [routes], [onGenerateRoute], or [onUnknownRoute], the `child` will
/// be null, and it is the responsibility of the [builder] to provide the
/// application's routing machinery.
///
/// If routes _are_ provided to the regular [WidgetsApp] constructor using one
/// or more of those properties or if the [WidgetsApp.router] constructor is
/// used, then `child` is not null, and the returned value should include the
/// `child` in the widget subtree; if it does not, then the application will
/// have no [Navigator] or [Router] and the routing related properties (i.e.
/// [navigatorKey], [home], [routes], [onGenerateRoute], [onUnknownRoute],
/// [initialRoute], [navigatorObservers], [routeInformationProvider],
/// [backButtonDispatcher], [routerDelegate], and [routeInformationParser])
/// are ignored.
///
/// If [builder] is null, it is as if a builder was specified that returned
/// the `child` directly. If it is null, routes must be provided using one of
...
...
@@ -605,8 +610,9 @@ class WidgetsApp extends StatefulWidget {
///
/// Unless a [Navigator] is provided, either implicitly from [builder] being
/// null, or by a [builder] including its `child` argument, or by a [builder]
/// explicitly providing a [Navigator] of its own, widgets and APIs such as
/// [Hero], [Navigator.push] and [Navigator.pop], will not function.
/// explicitly providing a [Navigator] of its own, or by the [routerDelegate]
/// building one, widgets and APIs such as [Hero], [Navigator.push] and
/// [Navigator.pop], will not function.
/// {@endtemplate}
final
TransitionBuilder
?
builder
;
...
...
@@ -1113,11 +1119,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
void
initState
()
{
super
.
initState
();
if
(
_usesRouter
)
{
_updateRouter
();
}
else
{
_updateNavigator
();
}
_updateRouting
();
_locale
=
_resolveLocales
(
WidgetsBinding
.
instance
!.
window
.
locales
,
widget
.
supportedLocales
);
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
...
...
@@ -1125,12 +1127,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
void
didUpdateWidget
(
WidgetsApp
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
routeInformationProvider
!=
widget
.
routeInformationProvider
)
{
_updateRouter
();
}
if
(
widget
.
navigatorKey
!=
oldWidget
.
navigatorKey
)
{
_updateNavigator
();
}
_updateRouting
(
oldWidget:
oldWidget
);
}
@override
...
...
@@ -1140,30 +1137,53 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
super
.
dispose
();
}
void
_updateRouting
({
WidgetsApp
?
oldWidget
})
{
if
(
_usesRouter
)
{
assert
(!
_usesNavigator
);
_navigator
=
null
;
if
(
oldWidget
==
null
||
oldWidget
.
routeInformationProvider
!=
widget
.
routeInformationProvider
)
{
_defaultRouteInformationProvider
?.
dispose
();
_defaultRouteInformationProvider
=
null
;
if
(
widget
.
routeInformationProvider
==
null
)
{
_defaultRouteInformationProvider
=
PlatformRouteInformationProvider
(
initialRouteInformation:
RouteInformation
(
location:
_initialRouteName
,
),
);
}
}
}
else
if
(
_usesNavigator
)
{
assert
(!
_usesRouter
);
_defaultRouteInformationProvider
?.
dispose
();
_defaultRouteInformationProvider
=
null
;
if
(
oldWidget
==
null
||
widget
.
navigatorKey
!=
oldWidget
.
navigatorKey
)
{
_navigator
=
widget
.
navigatorKey
??
GlobalObjectKey
<
NavigatorState
>(
this
);
}
assert
(
_navigator
!=
null
);
}
else
{
assert
(
widget
.
builder
!=
null
);
assert
(!
_usesRouter
);
assert
(!
_usesNavigator
);
_navigator
=
null
;
_defaultRouteInformationProvider
?.
dispose
();
_defaultRouteInformationProvider
=
null
;
}
// If we use a navigator, we have a navigator key.
assert
(
_usesNavigator
==
(
_navigator
!=
null
));
}
bool
get
_usesRouter
=>
widget
.
routerDelegate
!=
null
;
bool
get
_usesNavigator
=>
widget
.
home
!=
null
||
widget
.
routes
?.
isNotEmpty
==
true
||
widget
.
onGenerateRoute
!=
null
||
widget
.
onUnknownRoute
!=
null
;
// ROUTER
RouteInformationProvider
?
get
_effectiveRouteInformationProvider
=>
widget
.
routeInformationProvider
??
_defaultRouteInformationProvider
;
PlatformRouteInformationProvider
?
_defaultRouteInformationProvider
;
void
_updateRouter
()
{
_defaultRouteInformationProvider
?.
dispose
();
if
(
widget
.
routeInformationProvider
==
null
)
_defaultRouteInformationProvider
=
PlatformRouteInformationProvider
(
initialRouteInformation:
RouteInformation
(
location:
_initialRouteName
,
),
);
}
// NAVIGATOR
GlobalKey
<
NavigatorState
>?
_navigator
;
void
_updateNavigator
()
{
_navigator
=
widget
.
navigatorKey
??
GlobalObjectKey
<
NavigatorState
>(
this
);
}
Route
<
dynamic
>?
_onGenerateRoute
(
RouteSettings
settings
)
{
final
String
?
name
=
settings
.
name
;
final
WidgetBuilder
?
pageContentBuilder
=
name
==
Navigator
.
defaultRouteName
&&
widget
.
home
!=
null
...
...
@@ -1476,7 +1496,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
Widget
build
(
BuildContext
context
)
{
Widget
routing
;
Widget
?
routing
;
if
(
_usesRouter
)
{
assert
(
_effectiveRouteInformationProvider
!=
null
);
routing
=
Router
<
Object
>(
...
...
@@ -1485,7 +1505,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
routerDelegate:
widget
.
routerDelegate
!,
backButtonDispatcher:
widget
.
backButtonDispatcher
,
);
}
else
{
}
else
if
(
_usesNavigator
)
{
assert
(
_navigator
!=
null
);
routing
=
Navigator
(
restorationScopeId:
'nav'
,
...
...
@@ -1512,7 +1532,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
);
}
else
{
assert
(
routing
!=
null
);
result
=
routing
;
result
=
routing
!
;
}
if
(
widget
.
textStyle
!=
null
)
{
...
...
packages/flutter/test/material/app_test.dart
View file @
1e0007f3
...
...
@@ -984,6 +984,17 @@ void main() {
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'popped'
),
findsOneWidget
);
});
testWidgets
(
'MaterialApp.builder can build app without a Navigator'
,
(
WidgetTester
tester
)
async
{
Widget
builderChild
;
await
tester
.
pumpWidget
(
MaterialApp
(
builder:
(
BuildContext
context
,
Widget
child
)
{
builderChild
=
child
;
return
Container
();
},
));
expect
(
builderChild
,
isNull
);
});
}
class
MockAccessibilityFeature
implements
AccessibilityFeatures
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment