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 {
...
@@ -568,14 +568,15 @@ class WidgetsApp extends StatefulWidget {
final
List
<
NavigatorObserver
>?
navigatorObservers
;
final
List
<
NavigatorObserver
>?
navigatorObservers
;
/// {@template flutter.widgets.widgetsApp.builder}
/// {@template flutter.widgets.widgetsApp.builder}
/// A builder for inserting widgets above the [Navigator] but below the other
/// A builder for inserting widgets above the [Navigator] or - when the
/// widgets created by the [WidgetsApp] widget, or for replacing the
/// [WidgetsApp.router] constructor is used - above the [Router] but below the
/// [Navigator] entirely.
/// other widgets created by the [WidgetsApp] widget, or for replacing the
/// [Navigator]/[Router] entirely.
///
///
/// For example, from the [BuildContext] passed to this method, the
/// For example, from the [BuildContext] passed to this method, the
/// [Directionality], [Localizations], [DefaultTextStyle], [MediaQuery], etc,
/// [Directionality], [Localizations], [DefaultTextStyle], [MediaQuery], etc,
/// are all available. They can also be overridden in a way that impacts all
/// 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
/// 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
/// override those defaults, e.g. to force the application into right-to-left
...
@@ -586,18 +587,22 @@ class WidgetsApp extends StatefulWidget {
...
@@ -586,18 +587,22 @@ class WidgetsApp extends StatefulWidget {
/// [Localizations], consider [onGenerateTitle] instead.
/// [Localizations], consider [onGenerateTitle] instead.
///
///
/// The [builder] callback is passed two arguments, the [BuildContext] (as
/// The [builder] callback is passed two arguments, the [BuildContext] (as
/// `context`) and a [Navigator] widget (as `child`).
/// `context`) and a [Navigator] or [Router] widget (as `child`).
///
///
/// If no routes are provided using [home], [routes], [onGenerateRoute], or
/// If no routes are provided to the regular [WidgetsApp] constructor using
/// [onUnknownRoute], the `child` will be null, and it is the responsibility
/// [home], [routes], [onGenerateRoute], or [onUnknownRoute], the `child` will
/// of the [builder] to provide the application's routing machinery.
/// 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
/// If routes _are_ provided to the regular [WidgetsApp] constructor using one
/// the widget subtree; if it does not, then the application will have no
/// or more of those properties or if the [WidgetsApp.router] constructor is
/// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute],
/// used, then `child` is not null, and the returned value should include the
/// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will
/// `child` in the widget subtree; if it does not, then the application will
/// have no effect.
/// 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
/// 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
/// the `child` directly. If it is null, routes must be provided using one of
...
@@ -605,8 +610,9 @@ class WidgetsApp extends StatefulWidget {
...
@@ -605,8 +610,9 @@ class WidgetsApp extends StatefulWidget {
///
///
/// Unless a [Navigator] is provided, either implicitly from [builder] being
/// Unless a [Navigator] is provided, either implicitly from [builder] being
/// null, or by a [builder] including its `child` argument, or by a [builder]
/// 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
/// explicitly providing a [Navigator] of its own, or by the [routerDelegate]
/// [Hero], [Navigator.push] and [Navigator.pop], will not function.
/// building one, widgets and APIs such as [Hero], [Navigator.push] and
/// [Navigator.pop], will not function.
/// {@endtemplate}
/// {@endtemplate}
final
TransitionBuilder
?
builder
;
final
TransitionBuilder
?
builder
;
...
@@ -1113,11 +1119,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1113,11 +1119,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
@override
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
if
(
_usesRouter
)
{
_updateRouting
();
_updateRouter
();
}
else
{
_updateNavigator
();
}
_locale
=
_resolveLocales
(
WidgetsBinding
.
instance
!.
window
.
locales
,
widget
.
supportedLocales
);
_locale
=
_resolveLocales
(
WidgetsBinding
.
instance
!.
window
.
locales
,
widget
.
supportedLocales
);
WidgetsBinding
.
instance
!.
addObserver
(
this
);
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
}
...
@@ -1125,12 +1127,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1125,12 +1127,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
@override
void
didUpdateWidget
(
WidgetsApp
oldWidget
)
{
void
didUpdateWidget
(
WidgetsApp
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
routeInformationProvider
!=
widget
.
routeInformationProvider
)
{
_updateRouting
(
oldWidget:
oldWidget
);
_updateRouter
();
}
if
(
widget
.
navigatorKey
!=
oldWidget
.
navigatorKey
)
{
_updateNavigator
();
}
}
}
@override
@override
...
@@ -1140,30 +1137,53 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1140,30 +1137,53 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
super
.
dispose
();
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
_usesRouter
=>
widget
.
routerDelegate
!=
null
;
bool
get
_usesNavigator
=>
widget
.
home
!=
null
||
widget
.
routes
?.
isNotEmpty
==
true
||
widget
.
onGenerateRoute
!=
null
||
widget
.
onUnknownRoute
!=
null
;
// ROUTER
// ROUTER
RouteInformationProvider
?
get
_effectiveRouteInformationProvider
=>
widget
.
routeInformationProvider
??
_defaultRouteInformationProvider
;
RouteInformationProvider
?
get
_effectiveRouteInformationProvider
=>
widget
.
routeInformationProvider
??
_defaultRouteInformationProvider
;
PlatformRouteInformationProvider
?
_defaultRouteInformationProvider
;
PlatformRouteInformationProvider
?
_defaultRouteInformationProvider
;
void
_updateRouter
()
{
_defaultRouteInformationProvider
?.
dispose
();
if
(
widget
.
routeInformationProvider
==
null
)
_defaultRouteInformationProvider
=
PlatformRouteInformationProvider
(
initialRouteInformation:
RouteInformation
(
location:
_initialRouteName
,
),
);
}
// NAVIGATOR
// NAVIGATOR
GlobalKey
<
NavigatorState
>?
_navigator
;
GlobalKey
<
NavigatorState
>?
_navigator
;
void
_updateNavigator
()
{
_navigator
=
widget
.
navigatorKey
??
GlobalObjectKey
<
NavigatorState
>(
this
);
}
Route
<
dynamic
>?
_onGenerateRoute
(
RouteSettings
settings
)
{
Route
<
dynamic
>?
_onGenerateRoute
(
RouteSettings
settings
)
{
final
String
?
name
=
settings
.
name
;
final
String
?
name
=
settings
.
name
;
final
WidgetBuilder
?
pageContentBuilder
=
name
==
Navigator
.
defaultRouteName
&&
widget
.
home
!=
null
final
WidgetBuilder
?
pageContentBuilder
=
name
==
Navigator
.
defaultRouteName
&&
widget
.
home
!=
null
...
@@ -1476,7 +1496,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1476,7 +1496,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
Widget
routing
;
Widget
?
routing
;
if
(
_usesRouter
)
{
if
(
_usesRouter
)
{
assert
(
_effectiveRouteInformationProvider
!=
null
);
assert
(
_effectiveRouteInformationProvider
!=
null
);
routing
=
Router
<
Object
>(
routing
=
Router
<
Object
>(
...
@@ -1485,7 +1505,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1485,7 +1505,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
routerDelegate:
widget
.
routerDelegate
!,
routerDelegate:
widget
.
routerDelegate
!,
backButtonDispatcher:
widget
.
backButtonDispatcher
,
backButtonDispatcher:
widget
.
backButtonDispatcher
,
);
);
}
else
{
}
else
if
(
_usesNavigator
)
{
assert
(
_navigator
!=
null
);
assert
(
_navigator
!=
null
);
routing
=
Navigator
(
routing
=
Navigator
(
restorationScopeId:
'nav'
,
restorationScopeId:
'nav'
,
...
@@ -1512,7 +1532,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1512,7 +1532,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
);
);
}
else
{
}
else
{
assert
(
routing
!=
null
);
assert
(
routing
!=
null
);
result
=
routing
;
result
=
routing
!
;
}
}
if
(
widget
.
textStyle
!=
null
)
{
if
(
widget
.
textStyle
!=
null
)
{
...
...
packages/flutter/test/material/app_test.dart
View file @
1e0007f3
...
@@ -984,6 +984,17 @@ void main() {
...
@@ -984,6 +984,17 @@ void main() {
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'popped'
),
findsOneWidget
);
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
{
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