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
f4f23ecb
Unverified
Commit
f4f23ecb
authored
Nov 08, 2021
by
Hans Muller
Committed by
GitHub
Nov 08, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added SharedAppData to the widgets library (#93175)
parent
6bc33812
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
564 additions
and
11 deletions
+564
-11
shared_app_data.0.dart
...es/api/lib/widgets/shared_app_data/shared_app_data.0.dart
+75
-0
shared_app_data.1.dart
...es/api/lib/widgets/shared_app_data/shared_app_data.1.dart
+66
-0
app.dart
packages/flutter/lib/src/widgets/app.dart
+14
-11
shared_app_data.dart
packages/flutter/lib/src/widgets/shared_app_data.dart
+201
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-0
debug_test.dart
packages/flutter/test/material/debug_test.dart
+2
-0
shared_app_data_test.dart
packages/flutter/test/widgets/shared_app_data_test.dart
+205
-0
No files found.
examples/api/lib/widgets/shared_app_data/shared_app_data.0.dart
0 → 100644
View file @
f4f23ecb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for SharedAppData
import
'package:flutter/material.dart'
;
class
ShowSharedValue
extends
StatelessWidget
{
const
ShowSharedValue
({
Key
?
key
,
required
this
.
appDataKey
})
:
super
(
key:
key
);
final
String
appDataKey
;
@override
Widget
build
(
BuildContext
context
)
{
// The SharedAppData.getValue() call here causes this widget to depend
// on the value of the SharedAppData's 'foo' key. If it's changed, with
// SharedAppData.setValue(), then this widget will be rebuilt.
final
String
value
=
SharedAppData
.
getValue
<
String
,
String
>(
context
,
appDataKey
,
()
=>
'initial'
);
return
Text
(
'
$appDataKey
:
$value
'
);
}
}
// Demonstrates that changes to the SharedAppData _only_ cause the dependent widgets
// to be rebuilt. In this case that's the ShowSharedValue widget that's
// displaying the value of a key whose value has been updated.
class
Home
extends
StatefulWidget
{
const
Home
({
Key
?
key
})
:
super
(
key:
key
);
@override
State
<
Home
>
createState
()
=>
_HomeState
();
}
class
_HomeState
extends
State
<
Home
>
{
int
_fooVersion
=
0
;
int
_barVersion
=
0
;
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
body:
Center
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
<
Widget
>[
const
ShowSharedValue
(
appDataKey:
'foo'
),
const
SizedBox
(
height:
16
),
const
ShowSharedValue
(
appDataKey:
'bar'
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
child:
const
Text
(
'change foo'
),
onPressed:
()
{
_fooVersion
+=
1
;
// Changing the SharedAppData's value for 'foo' causes the widgets that
// depend on 'foo' to be rebuilt.
SharedAppData
.
setValue
<
String
,
String
?>(
context
,
'foo'
,
'FOO
$_fooVersion
'
);
// note: no setState()
},
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
child:
const
Text
(
'change bar'
),
onPressed:
()
{
_barVersion
+=
1
;
SharedAppData
.
setValue
<
String
,
String
?>(
context
,
'bar'
,
'BAR
$_barVersion
'
);
// note: no setState()
},
),
],
),
),
);
}
}
void
main
(
)
{
runApp
(
const
MaterialApp
(
home:
Home
()));
}
examples/api/lib/widgets/shared_app_data/shared_app_data.1.dart
0 → 100644
View file @
f4f23ecb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for SharedAppData
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
// A single lazily constructed object that's shared with the entire
// application via `SharedObject.of(context)`. The value of the object
// can be changed with `SharedObject.reset(context)`. Resetting the value
// will cause all of the widgets that depend on it to be rebuilt.
class
SharedObject
{
SharedObject
.
_
();
static
final
Object
_sharedObjectKey
=
Object
();
@override
String
toString
()
=>
describeIdentity
(
this
);
static
void
reset
(
BuildContext
context
)
{
// Calling SharedAppData.setValue() causes dependent widgets to be rebuilt.
SharedAppData
.
setValue
<
Object
,
SharedObject
>(
context
,
_sharedObjectKey
,
SharedObject
.
_
());
}
static
SharedObject
of
(
BuildContext
context
)
{
// If a value for _sharedObjectKey has never been set then the third
// callback parameter is used to generate an initial value.
return
SharedAppData
.
getValue
<
Object
,
SharedObject
>(
context
,
_sharedObjectKey
,
()
=>
SharedObject
.
_
());
}
}
// An example of a widget which depends on the SharedObject's value,
// which might be provided - along with SharedObject - in a Dart package.
class
CustomWidget
extends
StatelessWidget
{
const
CustomWidget
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
// Will be rebuilt if the shared object's value is changed.
return
ElevatedButton
(
child:
Text
(
'Replace
${SharedObject.of(context)}
'
),
onPressed:
()
{
SharedObject
.
reset
(
context
);
},
);
}
}
class
Home
extends
StatelessWidget
{
const
Home
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
const
Scaffold
(
body:
Center
(
child:
CustomWidget
()
),
);
}
}
void
main
(
)
{
runApp
(
const
MaterialApp
(
home:
Home
()));
}
packages/flutter/lib/src/widgets/app.dart
View file @
f4f23ecb
...
@@ -24,6 +24,7 @@ import 'restoration.dart';
...
@@ -24,6 +24,7 @@ import 'restoration.dart';
import
'router.dart'
;
import
'router.dart'
;
import
'scrollable.dart'
;
import
'scrollable.dart'
;
import
'semantics_debugger.dart'
;
import
'semantics_debugger.dart'
;
import
'shared_app_data.dart'
;
import
'shortcuts.dart'
;
import
'shortcuts.dart'
;
import
'text.dart'
;
import
'text.dart'
;
import
'title.dart'
;
import
'title.dart'
;
...
@@ -1664,17 +1665,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
...
@@ -1664,17 +1665,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
return
RootRestorationScope
(
return
RootRestorationScope
(
restorationId:
widget
.
restorationScopeId
,
restorationId:
widget
.
restorationScopeId
,
child:
Shortcuts
(
child:
SharedAppData
(
debugLabel:
'<Default WidgetsApp Shortcuts>'
,
child:
Shortcuts
(
shortcuts:
widget
.
shortcuts
??
WidgetsApp
.
defaultShortcuts
,
debugLabel:
'<Default WidgetsApp Shortcuts>'
,
// DefaultTextEditingShortcuts is nested inside Shortcuts so that it can
shortcuts:
widget
.
shortcuts
??
WidgetsApp
.
defaultShortcuts
,
// fall through to the defaultShortcuts.
// DefaultTextEditingShortcuts is nested inside Shortcuts so that it can
child:
DefaultTextEditingShortcuts
(
// fall through to the defaultShortcuts.
child:
Actions
(
child:
DefaultTextEditingShortcuts
(
actions:
widget
.
actions
??
WidgetsApp
.
defaultActions
,
child:
Actions
(
child:
FocusTraversalGroup
(
actions:
widget
.
actions
??
WidgetsApp
.
defaultActions
,
policy:
ReadingOrderTraversalPolicy
(),
child:
FocusTraversalGroup
(
child:
child
,
policy:
ReadingOrderTraversalPolicy
(),
child:
child
,
),
),
),
),
),
),
),
...
...
packages/flutter/lib/src/widgets/shared_app_data.dart
0 → 100644
View file @
f4f23ecb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'framework.dart'
;
import
'inherited_model.dart'
;
/// The type of the [SharedAppData.getValue] `init` parameter.
///
/// This callback is used to lazily create the initial value for
/// a [SharedAppData] keyword.
typedef
SharedAppDataInitCallback
<
T
>
=
T
Function
();
/// Enables sharing key/value data with its `child` and all of the
/// child's descendants.
///
/// - `SharedAppData.getValue(context, key, initCallback)` creates a dependency
/// on the key and returns the value for the key from the shared data table.
/// If no value exists for key then the initCallback is used to create
/// the initial value.
///
/// - `SharedAppData.setValue(context, key, value)` changes the value of an entry
/// in the shared data table and forces widgets that depend on that entry
/// to be rebuilt.
///
/// A widget whose build method uses SharedAppData.getValue(context,
/// keyword, initCallback) creates a dependency on the SharedAppData. When
/// the value of keyword changes with SharedAppData.setValue(), the widget
/// will be rebuilt. The values managed by the SharedAppData are expected
/// to be immutable: intrinsic changes to values will not cause
/// dependent widgets to be rebuilt.
///
/// An instance of this widget is created automatically by [WidgetsApp].
///
/// There are many ways to share data with a widget subtree. This
/// class is based on [InheritedModel], which is an [InheritedWidget].
/// It's intended to be used by packages that need to share a modest
/// number of values among their own components.
///
/// SharedAppData is not intended to be a substitute for Provider or any of
/// the other general purpose application state systems. SharedAppData is
/// for situations where a package's custom widgets need to share one
/// or a handful of immutable data objects that can be lazily
/// initialized. It exists so that packages like that can deliver
/// custom widgets without requiring the developer to add a
/// package-specific umbrella widget to their application.
///
/// A good way to create an SharedAppData key that avoids potential
/// collisions with other packages is to use a static `Object()` value.
/// The `SharedObject` example below does this.
///
/// {@tool dartpad}
/// The following sample demonstrates using the automatically created
/// `SharedAppData`. Button presses cause changes to the values for keys
/// 'foo', and 'bar', and those changes only cause the widgets that
/// depend on those keys to be rebuilt.
///
/// ** See code in examples/api/lib/widgets/shared_app_data/shared_app_data.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// The following sample demonstrates how a single lazily computed
/// value could be shared within an app. A Flutter package that
/// provided custom widgets might use this approach to share a (possibly
/// private) value with instances of those widgets.
///
/// ** See code in examples/api/lib/widgets/shared_app_data/shared_app_data.1.dart **
/// {@end-tool}
class
SharedAppData
extends
StatefulWidget
{
/// Creates a widget based on [InheritedModel] that supports build
/// dependencies qualified by keywords. Descendant widgets create
/// such dependencies with [SharedAppData.getValue] and they trigger
/// rebuilds with [SharedAppData.setValue].
///
/// This widget is automatically created by the [WidgetsApp].
const
SharedAppData
({
Key
?
key
,
required
this
.
child
})
:
super
(
key:
key
);
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final
Widget
child
;
@override
State
<
StatefulWidget
>
createState
()
=>
_SharedAppDataState
();
/// Returns the app model's value for `key` and ensures that each
/// time the value of `key` is changed with [SharedAppData.setValue], the
/// specified context will be rebuilt.
///
/// If no value for `key` exists then the `init` callback is used to
/// generate an initial value. The callback is expected to return
/// an immutable value because intrinsic changes to the value will
/// not cause dependent widgets to be rebuilt.
///
/// A widget that depends on the app model's value for `key` should use
/// this method in their `build` methods to ensure that they are rebuilt
/// if the value changes.
///
/// The type parameter `K` is the type of the keyword and `V`
/// is the type of the value.
static
V
getValue
<
K
extends
Object
,
V
>(
BuildContext
context
,
K
key
,
SharedAppDataInitCallback
<
V
>
init
)
{
final
_SharedAppModel
?
model
=
InheritedModel
.
inheritFrom
<
_SharedAppModel
>(
context
,
aspect:
key
);
assert
(
_debugHasSharedAppData
(
model
,
context
,
'getValue'
));
return
model
!.
sharedAppDataState
.
getValue
<
K
,
V
>(
key
,
init
);
}
/// Changes the app model's `value` for `key` and rebuilds any widgets
/// that have created a dependency on `key` with [SharedAppData.getValue].
///
/// If `value` is `==` to the current value of `key` then nothing
/// is rebuilt.
///
/// The `value` is expected to be immutable because intrinsic
/// changes to the value will not cause dependent widgets to be
/// rebuilt.
///
/// Unlike [SharedAppData.getValue], this method does _not_ create a dependency
/// between `context` and `key`.
///
/// The type parameter `K` is the type of the value's keyword and `V`
/// is the type of the value.
static
void
setValue
<
K
extends
Object
,
V
>(
BuildContext
context
,
K
key
,
V
value
)
{
final
_SharedAppModel
?
model
=
context
.
getElementForInheritedWidgetOfExactType
<
_SharedAppModel
>()?.
widget
as
_SharedAppModel
?;
assert
(
_debugHasSharedAppData
(
model
,
context
,
'setValue'
));
model
!.
sharedAppDataState
.
setValue
<
K
,
V
>(
key
,
value
);
}
static
bool
_debugHasSharedAppData
(
_SharedAppModel
?
model
,
BuildContext
context
,
String
methodName
)
{
assert
(()
{
if
(
model
==
null
)
{
throw
FlutterError
.
fromParts
(
<
DiagnosticsNode
>[
ErrorSummary
(
'No SharedAppData widget found.'
),
ErrorDescription
(
'SharedAppData.
$methodName
requires an SharedAppData widget ancestor.
\n
'
),
context
.
describeWidget
(
'The specific widget that could not find an SharedAppData ancestor was'
),
context
.
describeOwnershipChain
(
'The ownership chain for the affected widget is'
),
ErrorHint
(
'Typically, the SharedAppData widget is introduced by the MaterialApp '
'or WidgetsApp widget at the top of your application widget tree. It '
'provides a key/value map of data that is shared with the entire '
'application.'
,
),
],
);
}
return
true
;
}());
return
true
;
}
}
class
_SharedAppDataState
extends
State
<
SharedAppData
>
{
late
Map
<
Object
,
Object
?>
data
=
<
Object
,
Object
?>{};
@override
Widget
build
(
BuildContext
context
)
{
return
_SharedAppModel
(
sharedAppDataState:
this
,
child:
widget
.
child
);
}
V
getValue
<
K
extends
Object
,
V
>(
K
key
,
SharedAppDataInitCallback
<
V
>
init
)
{
data
[
key
]
??=
init
();
return
data
[
key
]
as
V
;
}
void
setValue
<
K
extends
Object
,
V
>(
K
key
,
V
value
)
{
if
(
data
[
key
]
!=
value
)
{
setState
(()
{
data
=
Map
<
Object
,
Object
?>.
from
(
data
);
data
[
key
]
=
value
;
});
}
}
}
class
_SharedAppModel
extends
InheritedModel
<
Object
>
{
_SharedAppModel
({
Key
?
key
,
required
this
.
sharedAppDataState
,
required
Widget
child
})
:
data
=
sharedAppDataState
.
data
,
super
(
key:
key
,
child:
child
);
final
_SharedAppDataState
sharedAppDataState
;
final
Map
<
Object
,
Object
?>
data
;
@override
bool
updateShouldNotify
(
_SharedAppModel
old
)
{
return
data
!=
old
.
data
;
}
@override
bool
updateShouldNotifyDependent
(
_SharedAppModel
old
,
Set
<
Object
>
keys
)
{
for
(
final
Object
key
in
keys
)
{
if
(
data
[
key
]
!=
old
.
data
[
key
])
{
return
true
;
}
}
return
false
;
}
}
packages/flutter/lib/widgets.dart
View file @
f4f23ecb
...
@@ -107,6 +107,7 @@ export 'src/widgets/scroll_view.dart';
...
@@ -107,6 +107,7 @@ export 'src/widgets/scroll_view.dart';
export
'src/widgets/scrollable.dart'
;
export
'src/widgets/scrollable.dart'
;
export
'src/widgets/scrollbar.dart'
;
export
'src/widgets/scrollbar.dart'
;
export
'src/widgets/semantics_debugger.dart'
;
export
'src/widgets/semantics_debugger.dart'
;
export
'src/widgets/shared_app_data.dart'
;
export
'src/widgets/shortcuts.dart'
;
export
'src/widgets/shortcuts.dart'
;
export
'src/widgets/single_child_scroll_view.dart'
;
export
'src/widgets/single_child_scroll_view.dart'
;
export
'src/widgets/size_changed_layout_notifier.dart'
;
export
'src/widgets/size_changed_layout_notifier.dart'
;
...
...
packages/flutter/test/material/debug_test.dart
View file @
f4f23ecb
...
@@ -200,6 +200,8 @@ void main() {
...
@@ -200,6 +200,8 @@ void main() {
' _FocusMarker
\n
'
' _FocusMarker
\n
'
' Focus
\n
'
' Focus
\n
'
' Shortcuts
\n
'
' Shortcuts
\n
'
' _SharedAppModel
\n
'
' SharedAppData
\n
'
' UnmanagedRestorationScope
\n
'
' UnmanagedRestorationScope
\n
'
' RestorationScope
\n
'
' RestorationScope
\n
'
' UnmanagedRestorationScope
\n
'
' UnmanagedRestorationScope
\n
'
...
...
packages/flutter/test/widgets/shared_app_data_test.dart
0 → 100644
View file @
f4f23ecb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'SharedAppData basics'
,
(
WidgetTester
tester
)
async
{
int
columnBuildCount
=
0
;
int
child1BuildCount
=
0
;
int
child2BuildCount
=
0
;
late
void
Function
(
BuildContext
context
)
setSharedAppDataValue
;
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
SharedAppData
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
columnBuildCount
+=
1
;
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
{
setSharedAppDataValue
.
call
(
context
);
},
child:
Column
(
children:
<
Widget
>[
Builder
(
builder:
(
BuildContext
context
)
{
child1BuildCount
+=
1
;
return
Text
(
SharedAppData
.
getValue
<
String
,
String
>(
context
,
'child1Text'
,
()
=>
'null'
));
},
),
Builder
(
builder:
(
BuildContext
context
)
{
child2BuildCount
+=
1
;
return
Text
(
SharedAppData
.
getValue
<
String
,
String
>(
context
,
'child2Text'
,
()
=>
'null'
));
}
),
],
),
);
},
),
),
),
);
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
1
);
expect
(
child2BuildCount
,
1
);
expect
(
find
.
text
(
'null'
).
evaluate
().
length
,
2
);
// SharedAppData.setValue<String, String>(context, 'child1Text', 'child1')
// causes the first Text widget to be rebuilt with its text to be
// set to 'child1'. Nothing else is rebuilt.
setSharedAppDataValue
=
(
BuildContext
context
)
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child1Text'
,
'child1'
);
};
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
2
);
expect
(
child2BuildCount
,
1
);
expect
(
find
.
text
(
'child1'
),
findsOneWidget
);
expect
(
find
.
text
(
'null'
),
findsOneWidget
);
// SharedAppData.setValue<String, String>(context, 'child2Text', 'child1')
// causes the second Text widget to be rebuilt with its text to be
// set to 'child2'. Nothing else is rebuilt.
setSharedAppDataValue
=
(
BuildContext
context
)
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child2Text'
,
'child2'
);
};
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
2
);
expect
(
child2BuildCount
,
2
);
expect
(
find
.
text
(
'child1'
),
findsOneWidget
);
expect
(
find
.
text
(
'child2'
),
findsOneWidget
);
// Resetting a key's value to the same value does not
// cause any widgets to be rebuilt.
setSharedAppDataValue
=
(
BuildContext
context
)
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child1Text'
,
'child1'
);
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child2Text'
,
'child2'
);
};
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
2
);
expect
(
child2BuildCount
,
2
);
// More of the same, resetting the values to null..
setSharedAppDataValue
=
(
BuildContext
context
)
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child1Text'
,
'null'
);
};
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
3
);
expect
(
child2BuildCount
,
2
);
expect
(
find
.
text
(
'null'
),
findsOneWidget
);
expect
(
find
.
text
(
'child2'
),
findsOneWidget
);
setSharedAppDataValue
=
(
BuildContext
context
)
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'child2Text'
,
'null'
);
};
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
columnBuildCount
,
1
);
expect
(
child1BuildCount
,
3
);
expect
(
child2BuildCount
,
3
);
expect
(
find
.
text
(
'null'
).
evaluate
().
length
,
2
);
});
testWidgets
(
'WidgetsApp SharedAppData '
,
(
WidgetTester
tester
)
async
{
int
parentBuildCount
=
0
;
int
childBuildCount
=
0
;
await
tester
.
pumpWidget
(
WidgetsApp
(
color:
const
Color
(
0xff00ff00
),
builder:
(
BuildContext
context
,
Widget
?
child
)
{
parentBuildCount
+=
1
;
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
{
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'childText'
,
'child'
);
},
child:
Center
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
childBuildCount
+=
1
;
return
Text
(
SharedAppData
.
getValue
<
String
,
String
>(
context
,
'childText'
,
()
=>
'null'
));
},
),
),
);
},
),
);
expect
(
find
.
text
(
'null'
),
findsOneWidget
);
expect
(
parentBuildCount
,
1
);
expect
(
childBuildCount
,
1
);
await
tester
.
tap
(
find
.
byType
(
GestureDetector
));
await
tester
.
pump
();
expect
(
parentBuildCount
,
1
);
expect
(
childBuildCount
,
2
);
expect
(
find
.
text
(
'child'
),
findsOneWidget
);
});
testWidgets
(
'WidgetsApp SharedAppData Shadowing'
,
(
WidgetTester
tester
)
async
{
int
innerTapCount
=
0
;
int
outerTapCount
=
0
;
await
tester
.
pumpWidget
(
WidgetsApp
(
color:
const
Color
(
0xff00ff00
),
builder:
(
BuildContext
context
,
Widget
?
child
)
{
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
{
outerTapCount
+=
1
;
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'childText'
,
'child'
);
},
child:
Center
(
child:
SharedAppData
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
innerTapCount
+=
1
;
SharedAppData
.
setValue
<
String
,
String
>(
context
,
'childText'
,
'child'
);
},
child:
Text
(
SharedAppData
.
getValue
<
String
,
String
>(
context
,
'childText'
,
()
=>
'null'
)),
);
},
),
),
),
);
},
),
);
expect
(
find
.
text
(
'null'
),
findsOneWidget
);
await
tester
.
tapAt
(
const
Offset
(
10
,
10
));
await
tester
.
pump
();
expect
(
outerTapCount
,
1
);
expect
(
innerTapCount
,
0
);
expect
(
find
.
text
(
'null'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
text
(
'null'
));
await
tester
.
pump
();
expect
(
outerTapCount
,
1
);
expect
(
innerTapCount
,
1
);
expect
(
find
.
text
(
'child'
),
findsOneWidget
);
});
}
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