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
f05bb9a1
Unverified
Commit
f05bb9a1
authored
Oct 28, 2023
by
Kostia Sokolovskyi
Committed by
GitHub
Oct 28, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Instrument RestorationBucket, _RouteEntry and DisposableBuildContext for leak tracking. (#137477)
parent
50ecd570
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
166 additions
and
4 deletions
+166
-4
restoration.dart
packages/flutter/lib/src/services/restoration.dart
+33
-0
disposable_build_context.dart
...ges/flutter/lib/src/widgets/disposable_build_context.dart
+18
-1
navigator.dart
packages/flutter/lib/src/widgets/navigator.dart
+16
-1
restoration_bucket_test.dart
packages/flutter/test/services/restoration_bucket_test.dart
+46
-0
restoration_test.dart
packages/flutter/test/services/restoration_test.dart
+2
-0
disposable_build_context_test.dart
...s/flutter/test/widgets/disposable_build_context_test.dart
+15
-0
restoration_mixin_test.dart
packages/flutter/test/widgets/restoration_mixin_test.dart
+8
-0
restoration_scope_test.dart
packages/flutter/test/widgets/restoration_scope_test.dart
+11
-0
root_restoration_scope_test.dart
...ges/flutter/test/widgets/root_restoration_scope_test.dart
+10
-2
scroll_aware_image_provider_test.dart
...lutter/test/widgets/scroll_aware_image_provider_test.dart
+7
-0
No files found.
packages/flutter/lib/src/services/restoration.dart
View file @
f05bb9a1
...
...
@@ -420,6 +420,12 @@ class RestorationManager extends ChangeNotifier {
_doSerialization
();
assert
(!
_serializationScheduled
);
}
@override
void
dispose
()
{
_rootBucket
?.
dispose
();
super
.
dispose
();
}
}
/// A [RestorationBucket] holds pieces of the restoration data that a part of
...
...
@@ -507,6 +513,9 @@ class RestorationBucket {
_debugOwner
=
debugOwner
;
return
true
;
}());
if
(
kFlutterMemoryAllocationsEnabled
)
{
_maybeDispatchObjectCreation
();
}
}
/// Creates the root [RestorationBucket] for the provided restoration
...
...
@@ -540,6 +549,9 @@ class RestorationBucket {
_debugOwner
=
manager
;
return
true
;
}());
if
(
kFlutterMemoryAllocationsEnabled
)
{
_maybeDispatchObjectCreation
();
}
}
/// Creates a child bucket initialized with the data that the provided
...
...
@@ -563,6 +575,9 @@ class RestorationBucket {
_debugOwner
=
debugOwner
;
return
true
;
}());
if
(
kFlutterMemoryAllocationsEnabled
)
{
_maybeDispatchObjectCreation
();
}
}
static
const
String
_childrenMapKey
=
'c'
;
...
...
@@ -934,6 +949,19 @@ class RestorationBucket {
_parent
?.
_addChildData
(
this
);
}
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
/// Dispatches event of object creation to [MemoryAllocations.instance].
void
_maybeDispatchObjectCreation
()
{
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectCreated
(
library
:
'package:flutter/services.dart'
,
className:
'
$RestorationBucket
'
,
object:
this
,
);
}
}
/// Deletes the bucket and all the data stored in it from the bucket
/// hierarchy.
///
...
...
@@ -948,6 +976,11 @@ class RestorationBucket {
/// This method must only be called by the object's owner.
void
dispose
()
{
assert
(
_debugAssertNotDisposed
());
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectDisposed
(
object:
this
);
}
_visitChildren
(
_dropChild
,
concurrentModification:
true
);
_claimedChildren
.
clear
();
_childrenToAdd
.
clear
();
...
...
packages/flutter/lib/src/widgets/disposable_build_context.dart
View file @
f05bb9a1
...
...
@@ -2,6 +2,8 @@
// 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'
;
/// Provides non-leaking access to a [BuildContext].
...
...
@@ -28,7 +30,17 @@ class DisposableBuildContext<T extends State> {
///
/// [State.mounted] must be true.
DisposableBuildContext
(
T
this
.
_state
)
:
assert
(
_state
.
mounted
,
'A DisposableBuildContext was given a BuildContext for an Element that is not mounted.'
);
:
assert
(
_state
.
mounted
,
'A DisposableBuildContext was given a BuildContext for an Element that is not mounted.'
)
{
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectCreated
(
library
:
'package:flutter/widgets.dart'
,
className:
'
$DisposableBuildContext
'
,
object:
this
,
);
}
}
T
?
_state
;
...
...
@@ -66,6 +78,11 @@ class DisposableBuildContext<T extends State> {
/// Creators of this object must call [dispose] when their [Element] is
/// unmounted, i.e. when [State.dispose] is called.
void
dispose
()
{
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectDisposed
(
object:
this
);
}
_state
=
null
;
}
}
packages/flutter/lib/src/widgets/navigator.dart
View file @
f05bb9a1
...
...
@@ -2913,7 +2913,17 @@ class _RouteEntry extends RouteTransitionRecord {
initialState
==
_RouteLifecycle
.
pushReplace
||
initialState
==
_RouteLifecycle
.
replace
,
),
currentState
=
initialState
;
currentState
=
initialState
{
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectCreated
(
library
:
'package:flutter/widgets.dart'
,
className:
'
$_RouteEntry
'
,
object:
this
,
);
}
}
@override
final
Route
<
dynamic
>
route
;
...
...
@@ -3125,6 +3135,11 @@ class _RouteEntry extends RouteTransitionRecord {
/// before disposing.
void
forcedDispose
()
{
assert
(
currentState
.
index
<
_RouteLifecycle
.
disposed
.
index
);
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if
(
kFlutterMemoryAllocationsEnabled
)
{
MemoryAllocations
.
instance
.
dispatchObjectDisposed
(
object:
this
);
}
currentState
=
_RouteLifecycle
.
disposed
;
route
.
dispose
();
}
...
...
packages/flutter/test/services/restoration_bucket_test.dart
View file @
f05bb9a1
...
...
@@ -6,6 +6,7 @@
import
'package:flutter/foundation.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'
;
import
'restoration.dart'
;
...
...
@@ -562,6 +563,51 @@ void main() {
expect
(()
=>
bucket
.
rename
(
'bar'
),
throwsFlutterError
);
expect
(()
=>
bucket
.
dispose
(),
throwsFlutterError
);
});
test
(
'
$RestorationBucket
dispatches memory events'
,
()
async
{
await
expectLater
(
await
memoryEvents
(
()
=>
RestorationBucket
.
empty
(
restorationId:
'child1'
,
debugOwner:
null
,
).
dispose
(),
RestorationBucket
,
),
areCreateAndDispose
,
);
final
MockRestorationManager
manager1
=
MockRestorationManager
();
addTearDown
(
manager1
.
dispose
);
await
expectLater
(
await
memoryEvents
(
()
=>
RestorationBucket
.
root
(
manager:
manager1
,
rawData:
null
,
).
dispose
(),
RestorationBucket
,
),
areCreateAndDispose
,
);
final
MockRestorationManager
manager2
=
MockRestorationManager
();
addTearDown
(
manager2
.
dispose
);
final
RestorationBucket
parent
=
RestorationBucket
.
root
(
manager:
manager2
,
rawData:
_createRawDataSet
()
);
addTearDown
(
parent
.
dispose
);
await
expectLater
(
await
memoryEvents
(
()
=>
RestorationBucket
.
child
(
restorationId:
'child1'
,
parent:
parent
,
debugOwner:
null
,
).
dispose
(),
RestorationBucket
,
),
areCreateAndDispose
,
);
});
}
Map
<
String
,
dynamic
>
_createRawDataSet
()
{
...
...
packages/flutter/test/services/restoration_test.dart
View file @
f05bb9a1
...
...
@@ -57,6 +57,7 @@ void main() {
expect
(
rootBucket
!.
read
<
int
>(
'value1'
),
10
);
expect
(
rootBucket
!.
read
<
String
>(
'value2'
),
'Hello'
);
final
RestorationBucket
child
=
rootBucket
!.
claimChild
(
'child1'
,
debugOwner:
null
);
addTearDown
(
child
.
dispose
);
expect
(
child
.
read
<
int
>(
'another value'
),
22
);
// Accessing the root bucket again completes synchronously with same bucket.
...
...
@@ -157,6 +158,7 @@ void main() {
expect
(
newRoot
!.
read
<
int
>(
'foo'
),
33
);
expect
(
newRoot
!.
read
<
int
>(
'value1'
),
null
);
final
RestorationBucket
newChild
=
newRoot
!.
claimChild
(
'childFoo'
,
debugOwner:
null
);
addTearDown
(
newChild
.
dispose
);
expect
(
newChild
.
read
<
String
>(
'bar'
),
'Hello'
);
});
...
...
packages/flutter/test/widgets/disposable_build_context_test.dart
View file @
f05bb9a1
...
...
@@ -30,6 +30,21 @@ void main() {
expect
(()
=>
DisposableBuildContext
(
state
),
throwsAssertionError
);
});
testWidgetsWithLeakTracking
(
'DisposableBuildContext dispatches memory events'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
TestWidgetState
>
key
=
GlobalKey
<
TestWidgetState
>();
await
tester
.
pumpWidget
(
TestWidget
(
key
));
final
TestWidgetState
state
=
key
.
currentState
!;
await
expectLater
(
await
memoryEvents
(
()
=>
DisposableBuildContext
<
TestWidgetState
>(
state
).
dispose
(),
DisposableBuildContext
<
TestWidgetState
>,
),
areCreateAndDispose
,
);
});
}
class
TestWidget
extends
StatefulWidget
{
...
...
packages/flutter/test/widgets/restoration_mixin_test.dart
View file @
f05bb9a1
...
...
@@ -15,6 +15,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
expect
(
rawData
,
isEmpty
);
await
tester
.
pumpWidget
(
...
...
@@ -41,6 +42,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
_createRawDataSet
());
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -64,6 +66,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
_createRawDataSet
());
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -107,6 +110,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
_createRawDataSet
());
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -144,6 +148,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
_createRawDataSet
();
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
expect
((
rawData
[
childrenMapKey
]
as
Map
<
String
,
dynamic
>).
containsKey
(
'child1'
),
isTrue
);
await
tester
.
pumpWidget
(
...
...
@@ -173,6 +178,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
_createRawDataSet
();
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -235,6 +241,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
_createRawDataSet
();
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
_TestRestorableWidget
(
...
...
@@ -297,6 +304,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
final
Key
key
=
GlobalKey
();
await
tester
.
pumpWidget
(
...
...
packages/flutter/test/widgets/restoration_scope_test.dart
View file @
f05bb9a1
...
...
@@ -15,6 +15,7 @@ void main() {
restorationId:
'foo'
,
debugOwner:
'owner'
,
);
addTearDown
(
bucket1
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -31,6 +32,8 @@ void main() {
restorationId:
'foo2'
,
debugOwner:
'owner'
,
);
addTearDown
(
bucket2
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
bucket:
bucket2
,
...
...
@@ -104,6 +107,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
expect
(
rawData
,
isEmpty
);
await
tester
.
pumpWidget
(
...
...
@@ -126,6 +130,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
_createRawDataSet
());
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -147,6 +152,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
_createRawDataSet
());
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -187,6 +193,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
_createRawDataSet
();
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
expect
((
rawData
[
childrenMapKey
]
as
Map
<
String
,
dynamic
>).
containsKey
(
'child1'
),
isTrue
);
await
tester
.
pumpWidget
(
...
...
@@ -216,6 +223,7 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
<
String
,
dynamic
>{});
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
...
...
@@ -274,6 +282,8 @@ void main() {
final
MockRestorationManager
manager
=
MockRestorationManager
();
addTearDown
(
manager
.
dispose
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
<
String
,
dynamic
>{});
addTearDown
(
root
.
dispose
);
await
tester
.
pumpWidget
(
UnmanagedRestorationScope
(
bucket:
root
,
...
...
@@ -316,6 +326,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
final
Key
scopeKey
=
GlobalKey
();
await
tester
.
pumpWidget
(
...
...
packages/flutter/test/widgets/root_restoration_scope_test.dart
View file @
f05bb9a1
...
...
@@ -27,6 +27,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
expect
(
rawData
,
isEmpty
);
await
tester
.
pumpWidget
(
...
...
@@ -77,6 +78,7 @@ void main() {
// Complete the future.
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
bucketCompleter
.
complete
(
root
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
...
...
@@ -92,6 +94,7 @@ void main() {
testWidgetsWithLeakTracking
(
'no delay when root is available synchronously'
,
(
WidgetTester
tester
)
async
{
final
Map
<
String
,
dynamic
>
rawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
rawData
);
addTearDown
(
root
.
dispose
);
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
>(
root
);
await
tester
.
pumpWidget
(
...
...
@@ -156,6 +159,7 @@ void main() {
// Complete the future.
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
<
String
,
dynamic
>{});
addTearDown
(
root
.
dispose
);
bucketCompleter
.
complete
(
root
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
...
...
@@ -187,6 +191,7 @@ void main() {
addTearDown
(
manager
.
dispose
);
final
Map
<
String
,
dynamic
>
inScopeRawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
inScopeRootBucket
=
RestorationBucket
.
root
(
manager:
manager
,
rawData:
inScopeRawData
);
addTearDown
(
inScopeRootBucket
.
dispose
);
await
tester
.
pumpWidget
(
Directionality
(
...
...
@@ -231,6 +236,7 @@ void main() {
final
Map
<
String
,
dynamic
>
outOfScopeRawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
outOfScopeRootBucket
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
outOfScopeRawData
);
addTearDown
(
outOfScopeRootBucket
.
dispose
);
bucketCompleter
.
complete
(
outOfScopeRootBucket
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
...
...
@@ -267,6 +273,7 @@ void main() {
testWidgetsWithLeakTracking
(
'injects new root when old one is decommissioned'
,
(
WidgetTester
tester
)
async
{
final
Map
<
String
,
dynamic
>
firstRawData
=
<
String
,
dynamic
>{};
final
RestorationBucket
firstRoot
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
firstRawData
);
addTearDown
(
firstRoot
.
dispose
);
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
>(
firstRoot
);
await
tester
.
pumpWidget
(
...
...
@@ -299,9 +306,9 @@ void main() {
},
};
final
RestorationBucket
secondRoot
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
secondRawData
);
addTearDown
(
secondRoot
.
dispose
);
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
>(
secondRoot
);
await
tester
.
pump
();
firstRoot
.
dispose
();
expect
(
state
.
bucket
,
isNot
(
same
(
firstBucket
)));
expect
(
state
.
bucket
!.
read
<
int
>(
'foo'
),
22
);
...
...
@@ -336,6 +343,7 @@ void main() {
expect
(
state
.
bucket
,
isNull
);
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
null
);
addTearDown
(
root
.
dispose
);
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
>(
root
);
await
tester
.
pump
();
...
...
@@ -346,6 +354,7 @@ void main() {
testWidgetsWithLeakTracking
(
'can switch to null'
,
(
WidgetTester
tester
)
async
{
final
RestorationBucket
root
=
RestorationBucket
.
root
(
manager:
binding
.
restorationManager
,
rawData:
null
);
addTearDown
(
root
.
dispose
);
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
>(
root
);
await
tester
.
pumpWidget
(
...
...
@@ -367,7 +376,6 @@ void main() {
binding
.
restorationManager
.
rootBucket
=
SynchronousFuture
<
RestorationBucket
?>(
null
);
await
tester
.
pump
();
root
.
dispose
();
expect
(
binding
.
restorationManager
.
rootBucketAccessed
,
2
);
expect
(
find
.
text
(
'Hello'
),
findsOneWidget
);
...
...
packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
View file @
f05bb9a1
...
...
@@ -39,6 +39,7 @@ void main() {
await
tester
.
pumpWidget
(
TestWidget
(
key
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
key
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -74,6 +75,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
key
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -115,6 +117,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
keys
.
last
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -173,6 +176,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
keys
.
last
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -241,6 +245,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
keys
.
last
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -307,6 +312,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
key
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
@@ -359,6 +365,7 @@ void main() {
));
final
DisposableBuildContext
context
=
DisposableBuildContext
(
key
.
currentState
!);
addTearDown
(
context
.
dispose
);
final
TestImageProvider
testImageProvider
=
TestImageProvider
(
testImage
.
clone
());
final
ScrollAwareImageProvider
<
TestImageProvider
>
imageProvider
=
ScrollAwareImageProvider
<
TestImageProvider
>(
context:
context
,
...
...
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