File tree 6 files changed +50
-14
lines changed
6 files changed +50
-14
lines changed Original file line number Diff line number Diff line change @@ -38,11 +38,11 @@ class SynchronousFuture<T> implements Future<T> {
38
38
39
39
@override
40
40
Future <R > then <R >(FutureOr <R > Function (T value) onValue, { Function ? onError }) {
41
- final dynamic result = onValue (_value);
41
+ final FutureOr < R > result = onValue (_value);
42
42
if (result is Future <R >) {
43
43
return result;
44
44
}
45
- return SynchronousFuture <R >(result as R );
45
+ return SynchronousFuture <R >(result);
46
46
}
47
47
48
48
@override
Original file line number Diff line number Diff line change @@ -247,17 +247,24 @@ abstract class CachingAssetBundle extends AssetBundle {
247
247
/// An [AssetBundle] that loads resources using platform messages.
248
248
class PlatformAssetBundle extends CachingAssetBundle {
249
249
@override
250
- Future <ByteData > load (String key) async {
250
+ Future <ByteData > load (String key) {
251
251
final Uint8List encoded = utf8.encoder.convert (Uri (path: Uri .encodeFull (key)).path);
252
- final ByteData ? asset =
253
- await ServicesBinding .instance.defaultBinaryMessenger.send ('flutter/assets' , encoded.buffer.asByteData ());
254
- if (asset == null ) {
252
+ final Future <ByteData >? future = ServicesBinding .instance.defaultBinaryMessenger.send ('flutter/assets' , encoded.buffer.asByteData ())? .then ((ByteData ? asset) {
253
+ if (asset == null ) {
254
+ throw FlutterError .fromParts (< DiagnosticsNode > [
255
+ _errorSummaryWithKey (key),
256
+ ErrorDescription ('The asset does not exist or has empty data.' ),
257
+ ]);
258
+ }
259
+ return asset;
260
+ });
261
+ if (future == null ) {
255
262
throw FlutterError .fromParts (< DiagnosticsNode > [
256
- _errorSummaryWithKey (key),
257
- ErrorDescription ('The asset does not exist or has empty data.' ),
258
- ]);
263
+ _errorSummaryWithKey (key),
264
+ ErrorDescription ('The asset does not exist or has empty data.' ),
265
+ ]);
259
266
}
260
- return asset ;
267
+ return future ;
261
268
}
262
269
263
270
@override
Original file line number Diff line number Diff line change @@ -645,7 +645,11 @@ class _FutureBuilderState<T> extends State<FutureBuilder<T>> {
645
645
}());
646
646
647
647
});
648
- _snapshot = _snapshot.inState (ConnectionState .waiting);
648
+ // An implementation like `SynchronousFuture` may have already called the
649
+ // .then closure. Do not overwrite it in that case.
650
+ if (_snapshot.connectionState != ConnectionState .done) {
651
+ _snapshot = _snapshot.inState (ConnectionState .waiting);
652
+ }
649
653
}
650
654
}
651
655
Original file line number Diff line number Diff line change 4
4
5
5
import 'dart:async' ;
6
6
7
+ import 'package:flutter/foundation.dart' ;
7
8
import 'package:flutter/widgets.dart' ;
8
9
import 'package:flutter_test/flutter_test.dart' ;
9
10
@@ -87,6 +88,20 @@ void main() {
87
88
});
88
89
});
89
90
group ('FutureBuilder' , () {
91
+ testWidgets ('gives expected snapshot with SynchronousFuture' , (WidgetTester tester) async {
92
+ final SynchronousFuture <String > future = SynchronousFuture <String >('flutter' );
93
+ await tester.pumpWidget (FutureBuilder <String >(
94
+ future: future,
95
+ builder: (BuildContext context, AsyncSnapshot <String > snapshot) {
96
+ expect (snapshot.connectionState, ConnectionState .done);
97
+ expect (snapshot.data, 'flutter' );
98
+ expect (snapshot.error, null );
99
+ expect (snapshot.stackTrace, null );
100
+ return const Placeholder ();
101
+ },
102
+ ));
103
+ });
104
+
90
105
testWidgets ('gracefully handles transition from null future' , (WidgetTester tester) async {
91
106
final GlobalKey key = GlobalKey ();
92
107
await tester.pumpWidget (FutureBuilder <String >(
Original file line number Diff line number Diff line change @@ -6,8 +6,8 @@ import 'dart:async';
6
6
import 'dart:convert' ;
7
7
import 'dart:io' ;
8
8
9
+ import 'package:flutter/foundation.dart' ;
9
10
import 'package:flutter/services.dart' ;
10
- import 'package:flutter/widgets.dart' ;
11
11
import 'package:path/path.dart' as path;
12
12
// ignore: deprecated_member_use
13
13
import 'package:test_api/test_api.dart' as test_package;
@@ -42,7 +42,7 @@ void mockFlutterAssets() {
42
42
/// platform messages.
43
43
SystemChannels .navigation.setMockMethodCallHandler ((MethodCall methodCall) async {});
44
44
45
- ServicesBinding .instance.defaultBinaryMessenger.setMockMessageHandler ('flutter/assets' , (ByteData ? message) async {
45
+ ServicesBinding .instance.defaultBinaryMessenger.setMockMessageHandler ('flutter/assets' , (ByteData ? message) {
46
46
assert (message != null );
47
47
String key = utf8.decode (message! .buffer.asUint8List ());
48
48
File asset = File (path.join (assetFolderPath, key));
@@ -62,7 +62,7 @@ void mockFlutterAssets() {
62
62
}
63
63
64
64
final Uint8List encoded = Uint8List .fromList (asset.readAsBytesSync ());
65
- return Future <ByteData >. value (encoded.buffer.asByteData ());
65
+ return SynchronousFuture <ByteData >(encoded.buffer.asByteData ());
66
66
});
67
67
}
68
68
Original file line number Diff line number Diff line change 10
10
import 'dart:async' ;
11
11
import 'dart:io' ;
12
12
13
+ import 'package:flutter/services.dart' ;
13
14
import 'package:flutter/widgets.dart' ;
14
15
import 'package:flutter_test/flutter_test.dart' ;
15
16
@@ -90,4 +91,13 @@ void main() {
90
91
binding.idle ();
91
92
});
92
93
});
94
+
95
+ testWidgets ('Assets in the tester can be loaded without turning event loop' , (WidgetTester tester) async {
96
+ bool responded = false ;
97
+ // The particular asset does not matter, as long as it exists.
98
+ rootBundle.load ('AssetManifest.json' ).then ((ByteData data) {
99
+ responded = true ;
100
+ });
101
+ expect (responded, true );
102
+ });
93
103
}
You can’t perform that action at this time.
0 commit comments