diff --git a/dev/benchmarks/complex_layout/test_memory/scroll_perf.dart b/dev/benchmarks/complex_layout/test_memory/scroll_perf.dart index 47dff1ac128..b05397dace1 100644 --- a/dev/benchmarks/complex_layout/test_memory/scroll_perf.dart +++ b/dev/benchmarks/complex_layout/test_memory/scroll_perf.dart @@ -32,7 +32,7 @@ Future main() async { child: ComplexLayoutApp(), ), )); - await SchedulerBinding.instance?.endOfFrame; + await SchedulerBinding.instance.endOfFrame; /// Wait 50ms to allow the raster thread to actually put up the frame. (The /// endOfFrame future ends when we send the data to the engine, before @@ -50,9 +50,9 @@ Future main() async { child: ComplexLayoutApp(), ), )); - await SchedulerBinding.instance?.endOfFrame; + await SchedulerBinding.instance.endOfFrame; - final WidgetController controller = LiveWidgetController(WidgetsBinding.instance!); + final WidgetController controller = LiveWidgetController(WidgetsBinding.instance); // Scroll down for (int iteration = 0; iteration < maxIterations; iteration += 1) { diff --git a/dev/benchmarks/macrobenchmarks/lib/src/filtered_child_animation.dart b/dev/benchmarks/macrobenchmarks/lib/src/filtered_child_animation.dart index 97bcbf7e090..236d18f91d9 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/filtered_child_animation.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/filtered_child_animation.dart @@ -41,7 +41,7 @@ class _FilteredChildAnimationPageState extends State _filterType = widget.initialFilterType; _complexChild = widget.initialComplexChild; _useRepaintBoundary = widget.initialUseRepaintBoundary; - WidgetsBinding.instance!.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { final RenderBox childBox = _childKey.currentContext!.findRenderObject()! as RenderBox; _childCenter = childBox.paintBounds.center; }); diff --git a/dev/benchmarks/macrobenchmarks/lib/src/large_images.dart b/dev/benchmarks/macrobenchmarks/lib/src/large_images.dart index 7d6fa003c5b..5bf34c53869 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/large_images.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/large_images.dart @@ -11,7 +11,7 @@ class LargeImagesPage extends StatelessWidget { @override Widget build(BuildContext context) { - final ImageCache imageCache = PaintingBinding.instance!.imageCache!; + final ImageCache imageCache = PaintingBinding.instance.imageCache; imageCache.maximumSize = 30; imageCache.maximumSizeBytes = 50 << 20; return GridView.builder( diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_hover.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_hover.dart index 1b3250c290d..62f848ae556 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_hover.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_hover.dart @@ -66,7 +66,7 @@ class BenchMouseRegionGridHover extends WidgetRecorder { void frameDidDraw() { if (!started) { started = true; - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async { _tester.start(); registerDidStop(_tester.stop); }); @@ -124,7 +124,7 @@ class _UntilNextFrame { static Future wait() { if (_UntilNextFrame._completer == null) { _UntilNextFrame._completer = Completer(); - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { _UntilNextFrame._completer!.complete(null); _UntilNextFrame._completer = null; }); @@ -145,7 +145,7 @@ class _Tester { TestGesture get gesture { return _gesture ??= TestGesture( dispatcher: (PointerEvent event) async { - RendererBinding.instance!.handlePointerEvent(event); + RendererBinding.instance.handlePointerEvent(event); }, kind: PointerDeviceKind.mouse, ); diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_scroll.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_scroll.dart index 55eb9f6784f..1f8775a30d7 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_scroll.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_grid_scroll.dart @@ -41,7 +41,7 @@ class BenchMouseRegionGridScroll extends WidgetRecorder { void frameDidDraw() { if (!started) { started = true; - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async { _tester.start(); registerDidStop(_tester.stop); }); @@ -96,7 +96,7 @@ class _UntilNextFrame { static Future wait() { if (_UntilNextFrame._completer == null) { _UntilNextFrame._completer = Completer(); - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { _UntilNextFrame._completer!.complete(null); _UntilNextFrame._completer = null; }); @@ -117,7 +117,7 @@ class _Tester { TestGesture get gesture { return _gesture ??= TestGesture( dispatcher: (PointerEvent event) async { - RendererBinding.instance!.handlePointerEvent(event); + RendererBinding.instance.handlePointerEvent(event); }, kind: PointerDeviceKind.mouse, ); diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_mixed_grid_hover.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_mixed_grid_hover.dart index 85c20fa0f64..bddc1078eb3 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_mixed_grid_hover.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_mouse_region_mixed_grid_hover.dart @@ -85,7 +85,7 @@ class BenchMouseRegionMixedGridHover extends WidgetRecorder { void frameDidDraw() { if (!started) { started = true; - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async { _tester.start(); registerDidStop(_tester.stop); }); @@ -146,7 +146,7 @@ class _UntilNextFrame { static Future wait() { if (_UntilNextFrame._completer == null) { _UntilNextFrame._completer = Completer(); - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { _UntilNextFrame._completer!.complete(null); _UntilNextFrame._completer = null; }); @@ -167,7 +167,7 @@ class _Tester { TestGesture get gesture { return _gesture ??= TestGesture( dispatcher: (PointerEvent event) async { - RendererBinding.instance!.handlePointerEvent(event); + RendererBinding.instance.handlePointerEvent(event); }, kind: PointerDeviceKind.mouse, ); diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart index e3e4637c68e..627f62a2b57 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart @@ -935,7 +935,7 @@ double _computeAverage(String label, Iterable values) { /// /// See also: /// -/// * https://en.wikipedia.org/wiki/Standard_deviation +/// * double _computeStandardDeviationForPopulation(String label, Iterable population) { if (population.isEmpty) { throw StateError('$label: attempted to compute the standard deviation of empty population.'); @@ -987,12 +987,32 @@ class _RecordingWidgetsBinding extends BindingBase SemanticsBinding, RendererBinding, WidgetsBinding { - /// Makes an instance of [_RecordingWidgetsBinding] the current binding. + + @override + void initInstances() { + super.initInstances(); + _instance = this; + } + + /// The singleton instance of this object. + /// + /// Provides access to the features exposed by this class. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [_RecordingWidgetsBinding.ensureInitialized]. + static _RecordingWidgetsBinding get instance => BindingBase.checkInstance(_instance); + static _RecordingWidgetsBinding? _instance; + + /// Returns an instance of the [_RecordingWidgetsBinding], creating and + /// initializing it if necessary. + /// + /// See also: + /// + /// * [WidgetsFlutterBinding.ensureInitialized], the equivalent in the widgets framework. static _RecordingWidgetsBinding ensureInitialized() { - if (WidgetsBinding.instance == null) { + if (_instance == null) { _RecordingWidgetsBinding(); } - return WidgetsBinding.instance! as _RecordingWidgetsBinding; + return instance; } FrameRecorder? _recorder; diff --git a/dev/benchmarks/macrobenchmarks/test/frame_policy.dart b/dev/benchmarks/macrobenchmarks/test/frame_policy.dart index 7e13444b549..16b08731bac 100644 --- a/dev/benchmarks/macrobenchmarks/test/frame_policy.dart +++ b/dev/benchmarks/macrobenchmarks/test/frame_policy.dart @@ -10,8 +10,7 @@ import 'package:integration_test/integration_test.dart'; import 'package:macrobenchmarks/src/simple_scroll.dart'; void main() { - final IntegrationTestWidgetsFlutterBinding binding = - IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets( 'Frame Counter and Input Delay for benchmarkLive', (WidgetTester tester) async { diff --git a/dev/benchmarks/macrobenchmarks/test_memory/heavy_gridview.dart b/dev/benchmarks/macrobenchmarks/test_memory/heavy_gridview.dart index 60a32c3880b..cf3bf61df31 100644 --- a/dev/benchmarks/macrobenchmarks/test_memory/heavy_gridview.dart +++ b/dev/benchmarks/macrobenchmarks/test_memory/heavy_gridview.dart @@ -10,8 +10,8 @@ import 'package:macrobenchmarks/main.dart'; Future endOfAnimation() async { do { - await SchedulerBinding.instance!.endOfFrame; - } while (SchedulerBinding.instance!.hasScheduledFrame); + await SchedulerBinding.instance.endOfFrame; + } while (SchedulerBinding.instance.hasScheduledFrame); } Future main() async { diff --git a/dev/benchmarks/macrobenchmarks/test_memory/large_images.dart b/dev/benchmarks/macrobenchmarks/test_memory/large_images.dart index 9c004a9e9cb..1b179227c99 100644 --- a/dev/benchmarks/macrobenchmarks/test_memory/large_images.dart +++ b/dev/benchmarks/macrobenchmarks/test_memory/large_images.dart @@ -10,8 +10,8 @@ import 'package:macrobenchmarks/main.dart'; Future endOfAnimation() async { do { - await SchedulerBinding.instance!.endOfFrame; - } while (SchedulerBinding.instance!.hasScheduledFrame); + await SchedulerBinding.instance.endOfFrame; + } while (SchedulerBinding.instance.hasScheduledFrame); } Future main() async { diff --git a/dev/benchmarks/microbenchmarks/lib/foundation/all_elements_bench.dart b/dev/benchmarks/microbenchmarks/lib/foundation/all_elements_bench.dart index 17029d141eb..26967f09166 100644 --- a/dev/benchmarks/microbenchmarks/lib/foundation/all_elements_bench.dart +++ b/dev/benchmarks/microbenchmarks/lib/foundation/all_elements_bench.dart @@ -44,24 +44,24 @@ Future main() async { // Wait for frame rendering to stabilize. for (int i = 0; i < 5; i++) { - await SchedulerBinding.instance?.endOfFrame; + await SchedulerBinding.instance.endOfFrame; } final Stopwatch watch = Stopwatch(); - print('flutter_test allElements benchmark... (${WidgetsBinding.instance?.renderViewElement})'); + print('flutter_test allElements benchmark... (${WidgetsBinding.instance.renderViewElement})'); // Make sure we get enough elements to process for consistent benchmark runs - int elementCount = collectAllElementsFrom(WidgetsBinding.instance!.renderViewElement!, skipOffstage: false).length; + int elementCount = collectAllElementsFrom(WidgetsBinding.instance.renderViewElement!, skipOffstage: false).length; while (elementCount < 2458) { await Future.delayed(Duration.zero); - elementCount = collectAllElementsFrom(WidgetsBinding.instance!.renderViewElement!, skipOffstage: false).length; + elementCount = collectAllElementsFrom(WidgetsBinding.instance.renderViewElement!, skipOffstage: false).length; } print('element count: $elementCount'); watch.start(); for (int i = 0; i < _kNumIters; i += 1) { final List allElements = collectAllElementsFrom( - WidgetsBinding.instance!.renderViewElement!, + WidgetsBinding.instance.renderViewElement!, skipOffstage: false, ).toList(); allElements.clear(); diff --git a/dev/benchmarks/microbenchmarks/lib/stocks/animation_bench.dart b/dev/benchmarks/microbenchmarks/lib/stocks/animation_bench.dart index 2e43c1fd120..d01b81915e1 100644 --- a/dev/benchmarks/microbenchmarks/lib/stocks/animation_bench.dart +++ b/dev/benchmarks/microbenchmarks/lib/stocks/animation_bench.dart @@ -68,7 +68,7 @@ Future main() async { // Time how long each frame takes cpuWatch.reset(); - while (SchedulerBinding.instance!.hasScheduledFrame) { + while (SchedulerBinding.instance.hasScheduledFrame) { await tester.pump(); totalSubsequentFramesIterationCount += 1; } diff --git a/dev/benchmarks/microbenchmarks/lib/stocks/layout_bench.dart b/dev/benchmarks/microbenchmarks/lib/stocks/layout_bench.dart index ade6023ba81..80e5c30d0b1 100644 --- a/dev/benchmarks/microbenchmarks/lib/stocks/layout_bench.dart +++ b/dev/benchmarks/microbenchmarks/lib/stocks/layout_bench.dart @@ -33,18 +33,18 @@ Future main() async { final TestViewConfiguration big = TestViewConfiguration( size: const Size(360.0, 640.0), - window: RendererBinding.instance?.window, + window: RendererBinding.instance.window, ); final TestViewConfiguration small = TestViewConfiguration( size: const Size(355.0, 635.0), - window: RendererBinding.instance?.window, + window: RendererBinding.instance.window, ); - final RenderView? renderView = WidgetsBinding.instance?.renderView; + final RenderView renderView = WidgetsBinding.instance.renderView; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.benchmark; watch.start(); while (watch.elapsed < kBenchmarkTime) { - renderView?.configuration = iterations.isEven ? big : small; + renderView.configuration = iterations.isEven ? big : small; await tester.pumpBenchmark(Duration(milliseconds: iterations * 16)); iterations += 1; } diff --git a/dev/integration_tests/abstract_method_smoke_test/lib/main.dart b/dev/integration_tests/abstract_method_smoke_test/lib/main.dart index f4ba87f7ce2..805e291b79d 100644 --- a/dev/integration_tests/abstract_method_smoke_test/lib/main.dart +++ b/dev/integration_tests/abstract_method_smoke_test/lib/main.dart @@ -42,7 +42,7 @@ class _HomePage extends State { // Trigger the second route. // https://github.com/flutter/flutter/issues/40126 - WidgetsBinding.instance?.addPostFrameCallback((_) async { + WidgetsBinding.instance.addPostFrameCallback((_) async { Navigator.of(context).push( MaterialPageRoute(builder: (_) => const SecondPage())); }); diff --git a/dev/integration_tests/flutter_gallery/test/calculator/smoke_test.dart b/dev/integration_tests/flutter_gallery/test/calculator/smoke_test.dart index 9ca841991b4..0fbb5de08b3 100644 --- a/dev/integration_tests/flutter_gallery/test/calculator/smoke_test.dart +++ b/dev/integration_tests/flutter_gallery/test/calculator/smoke_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_gallery/demo/calculator_demo.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test/drawer_test.dart b/dev/integration_tests/flutter_gallery/test/drawer_test.dart index 02bf621ac38..0ba0894fa55 100644 --- a/dev/integration_tests/flutter_gallery/test/drawer_test.dart +++ b/dev/integration_tests/flutter_gallery/test/drawer_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_gallery/gallery/app.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test/example_code_display_test.dart b/dev/integration_tests/flutter_gallery/test/example_code_display_test.dart index 27e45a03862..b39bc1c56b2 100644 --- a/dev/integration_tests/flutter_gallery/test/example_code_display_test.dart +++ b/dev/integration_tests/flutter_gallery/test/example_code_display_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test/live_smoketest.dart b/dev/integration_tests/flutter_gallery/test/live_smoketest.dart index 0e712c312d9..20a1b7b9001 100644 --- a/dev/integration_tests/flutter_gallery/test/live_smoketest.dart +++ b/dev/integration_tests/flutter_gallery/test/live_smoketest.dart @@ -58,7 +58,7 @@ Future main() async { print('Starting app...'); runApp(const GalleryApp(testMode: true)); - final _LiveWidgetController controller = _LiveWidgetController(WidgetsBinding.instance!); + final _LiveWidgetController controller = _LiveWidgetController(WidgetsBinding.instance); for (final GalleryDemoCategory category in kAllGalleryDemoCategories) { print('Tapping "${category.name}" section...'); await controller.tap(find.text(category.name)); @@ -111,7 +111,7 @@ class _LiveWidgetController extends LiveWidgetController { Future _waitUntilFrame(bool Function() condition, [Completer? completer]) { completer ??= Completer(); if (!condition()) { - SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { _waitUntilFrame(condition, completer); }); } else { diff --git a/dev/integration_tests/flutter_gallery/test/pesto_test.dart b/dev/integration_tests/flutter_gallery/test/pesto_test.dart index 8c20193a4c6..817f4907373 100644 --- a/dev/integration_tests/flutter_gallery/test/pesto_test.dart +++ b/dev/integration_tests/flutter_gallery/test/pesto_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test/simple_smoke_test.dart b/dev/integration_tests/flutter_gallery/test/simple_smoke_test.dart index 96583216065..050cb12aedd 100644 --- a/dev/integration_tests/flutter_gallery/test/simple_smoke_test.dart +++ b/dev/integration_tests/flutter_gallery/test/simple_smoke_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart' show GalleryApp; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test/smoke_test.dart b/dev/integration_tests/flutter_gallery/test/smoke_test.dart index fba23538914..2dc9a4339e3 100644 --- a/dev/integration_tests/flutter_gallery/test/smoke_test.dart +++ b/dev/integration_tests/flutter_gallery/test/smoke_test.dart @@ -77,9 +77,9 @@ Future smokeDemo(WidgetTester tester, GalleryDemo demo) async { // Verify that the dumps are pretty. final String routeName = demo.routeName; - verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance!.renderViewElement!.toStringDeep()); - verifyToStringOutput('debugDumpRenderTree', routeName, RendererBinding.instance?.renderView.toStringDeep() ?? ''); - verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? ''); + verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance.renderViewElement!.toStringDeep()); + verifyToStringOutput('debugDumpRenderTree', routeName, RendererBinding.instance.renderView.toStringDeep()); + verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance.renderView.debugLayer?.toStringDeep() ?? ''); // Scroll the demo around a bit more. await tester.flingFrom(const Offset(400.0, 300.0), const Offset(0.0, 400.0), 1000.0); @@ -179,8 +179,8 @@ void main() { testWidgets('Flutter Gallery app smoke test', smokeGallery); testWidgets('Flutter Gallery app smoke test with semantics', (WidgetTester tester) async { - RendererBinding.instance!.setSemanticsEnabled(true); + RendererBinding.instance.setSemanticsEnabled(true); await smokeGallery(tester); - RendererBinding.instance!.setSemanticsEnabled(false); + RendererBinding.instance.setSemanticsEnabled(false); }); } diff --git a/dev/integration_tests/flutter_gallery/test/update_test.dart b/dev/integration_tests/flutter_gallery/test/update_test.dart index 92024da0bae..160bb966903 100644 --- a/dev/integration_tests/flutter_gallery/test/update_test.dart +++ b/dev/integration_tests/flutter_gallery/test/update_test.dart @@ -11,7 +11,7 @@ Future mockUpdateUrlFetcher() { } void main() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); if (binding is LiveTestWidgetsFlutterBinding) binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart index 7af3adbf1ab..dfef691719b 100644 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf.dart @@ -30,12 +30,12 @@ class _MessageHandler { case 'demoNames': return const JsonEncoder.withIndent(' ').convert(_allDemos); case 'profileDemos': - controller ??= LiveWidgetController(WidgetsBinding.instance!); + controller ??= LiveWidgetController(WidgetsBinding.instance); await runDemos(kProfiledDemos, controller!); _unTestedDemos.removeAll(kProfiledDemos); return const JsonEncoder.withIndent(' ').convert(kProfiledDemos); case 'restDemos': - controller ??= LiveWidgetController(WidgetsBinding.instance!); + controller ??= LiveWidgetController(WidgetsBinding.instance); final List restDemos = _unTestedDemos.toList(); await runDemos(restDemos, controller!); return const JsonEncoder.withIndent(' ').convert(restDemos); diff --git a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart index cb3a81730a8..5097949a4fb 100644 --- a/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart +++ b/dev/integration_tests/flutter_gallery/test_driver/transitions_perf_e2e.dart @@ -22,8 +22,7 @@ List _allDemos = kAllGalleryDemos.map( void main([List args = const []]) { final bool withSemantics = args.contains('--with_semantics'); - final IntegrationTestWidgetsFlutterBinding binding = - IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; group('flutter gallery transitions on e2e', () { testWidgets('find.bySemanticsLabel', (WidgetTester tester) async { diff --git a/dev/integration_tests/flutter_gallery/test_memory/back_button.dart b/dev/integration_tests/flutter_gallery/test_memory/back_button.dart index ed17daa047d..140a45a29cb 100644 --- a/dev/integration_tests/flutter_gallery/test_memory/back_button.dart +++ b/dev/integration_tests/flutter_gallery/test_memory/back_button.dart @@ -11,8 +11,8 @@ import 'package:flutter_test/flutter_test.dart'; Future endOfAnimation() async { do { - await SchedulerBinding.instance!.endOfFrame; - } while (SchedulerBinding.instance!.hasScheduledFrame); + await SchedulerBinding.instance.endOfFrame; + } while (SchedulerBinding.instance.hasScheduledFrame); } int iteration = 0; @@ -30,5 +30,5 @@ Future main() async { await endOfAnimation(); await Future.delayed(const Duration(milliseconds: 50)); debugPrint('==== MEMORY BENCHMARK ==== READY ===='); - WidgetsBinding.instance!.addObserver(LifecycleObserver()); + WidgetsBinding.instance.addObserver(LifecycleObserver()); } diff --git a/dev/integration_tests/flutter_gallery/test_memory/image_cache_memory.dart b/dev/integration_tests/flutter_gallery/test_memory/image_cache_memory.dart index 4c58585b65b..0533a5fca34 100644 --- a/dev/integration_tests/flutter_gallery/test_memory/image_cache_memory.dart +++ b/dev/integration_tests/flutter_gallery/test_memory/image_cache_memory.dart @@ -38,7 +38,7 @@ Future main() async { ), )); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; // We are waiting for the GPU to rasterize a frame here. This makes this // flaky, we can rely on a more deterministic source such as @@ -48,7 +48,7 @@ Future main() async { debugPrint('==== MEMORY BENCHMARK ==== READY ===='); final WidgetController controller = - LiveWidgetController(WidgetsBinding.instance!); + LiveWidgetController(WidgetsBinding.instance); debugPrint('Scrolling...'); final Finder list = find.byKey(const Key('ImageList')); diff --git a/dev/integration_tests/flutter_gallery/test_memory/memory_nav.dart b/dev/integration_tests/flutter_gallery/test_memory/memory_nav.dart index 67b47692f60..5bfd47c2ded 100644 --- a/dev/integration_tests/flutter_gallery/test_memory/memory_nav.dart +++ b/dev/integration_tests/flutter_gallery/test_memory/memory_nav.dart @@ -13,8 +13,8 @@ import 'package:flutter_test/flutter_test.dart'; Future endOfAnimation() async { do { - await SchedulerBinding.instance!.endOfFrame; - } while (SchedulerBinding.instance!.hasScheduledFrame); + await SchedulerBinding.instance.endOfFrame; + } while (SchedulerBinding.instance.hasScheduledFrame); } Rect boundsFor(WidgetController controller, Finder item) { @@ -35,7 +35,7 @@ Future main() async { child: GalleryApp(testMode: true), ), )); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; await Future.delayed(const Duration(milliseconds: 50)); debugPrint('==== MEMORY BENCHMARK ==== READY ===='); @@ -49,9 +49,9 @@ Future main() async { child: GalleryApp(testMode: true), ), )); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; - final WidgetController controller = LiveWidgetController(WidgetsBinding.instance!); + final WidgetController controller = LiveWidgetController(WidgetsBinding.instance); debugPrint('Navigating...'); await controller.tap(find.text('Material')); diff --git a/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart b/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart index 5140437291b..c73f2bfcfa8 100644 --- a/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart +++ b/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart @@ -16,7 +16,7 @@ void main() { // Disconnects semantics listener for testing purposes. originalSemanticsListener = ui.window.onSemanticsEnabledChanged; ui.window.onSemanticsEnabledChanged = null; - RendererBinding.instance?.setSemanticsEnabled(false); + RendererBinding.instance.setSemanticsEnabled(false); // If the test passes, LifeCycleSpy will rewire the semantics listener back. runApp(const LifeCycleSpy()); } @@ -46,15 +46,15 @@ class _LifeCycleSpyState extends State with WidgetsBindingObserver @override void initState() { super.initState(); - WidgetsBinding.instance?.addObserver(this); + WidgetsBinding.instance.addObserver(this); _actualLifeCycleSequence = [ - ServicesBinding.instance?.lifecycleState + ServicesBinding.instance.lifecycleState ]; } @override void dispose() { - WidgetsBinding.instance?.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -70,7 +70,7 @@ class _LifeCycleSpyState extends State with WidgetsBindingObserver Widget build(BuildContext context) { if (const ListEquality().equals(_actualLifeCycleSequence, _expectedLifeCycleSequence)) { // Rewires the semantics harness if test passes. - RendererBinding.instance?.setSemanticsEnabled(true); + RendererBinding.instance.setSemanticsEnabled(true); ui.window.onSemanticsEnabledChanged = originalSemanticsListener; } return const MaterialApp( diff --git a/dev/manual_tests/lib/text.dart b/dev/manual_tests/lib/text.dart index 6facdf210c1..e86f1e312cf 100644 --- a/dev/manual_tests/lib/text.dart +++ b/dev/manual_tests/lib/text.dart @@ -960,7 +960,7 @@ class _PaintingState extends State with SingleTickerProviderStateMixin } _text = buffer.toString(); }); - SchedulerBinding.instance?.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { if (mounted && intrinsicKey.currentContext?.size?.height != controlKey.currentContext?.size?.height) { debugPrint('Found some text that unexpectedly renders at different heights.'); debugPrint('Text: $_text'); diff --git a/dev/tracing_tests/test/image_cache_tracing_test.dart b/dev/tracing_tests/test/image_cache_tracing_test.dart index 0ef752d3f3f..1f25959b230 100644 --- a/dev/tracing_tests/test/image_cache_tracing_test.dart +++ b/dev/tracing_tests/test/image_cache_tracing_test.dart @@ -32,18 +32,18 @@ void main() { test('Image cache tracing', () async { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); final TestImageStreamCompleter completer2 = TestImageStreamCompleter(); - PaintingBinding.instance!.imageCache!.putIfAbsent( + PaintingBinding.instance.imageCache.putIfAbsent( 'Test', () => completer1, ); - PaintingBinding.instance!.imageCache!.clear(); + PaintingBinding.instance.imageCache.clear(); completer2.testSetImage(ImageInfo(image: await createTestImage())); - PaintingBinding.instance!.imageCache!.putIfAbsent( + PaintingBinding.instance.imageCache.putIfAbsent( 'Test2', () => completer2, ); - PaintingBinding.instance!.imageCache!.evict('Test2'); + PaintingBinding.instance.imageCache.evict('Test2'); final Timeline timeline = await vmService.getVMTimeline(); _expectTimelineEvents( diff --git a/examples/layers/services/lifecycle.dart b/examples/layers/services/lifecycle.dart index 9297d732604..5472e1987b6 100644 --- a/examples/layers/services/lifecycle.dart +++ b/examples/layers/services/lifecycle.dart @@ -18,12 +18,12 @@ class _LifecycleWatcherState extends State @override void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); } @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } diff --git a/examples/layers/test/smoketests/rendering/custom_coordinate_systems_test.dart b/examples/layers/test/smoketests/rendering/custom_coordinate_systems_test.dart index 20cccb7a6dc..baf93bb54da 100644 --- a/examples/layers/test/smoketests/rendering/custom_coordinate_systems_test.dart +++ b/examples/layers/test/smoketests/rendering/custom_coordinate_systems_test.dart @@ -13,6 +13,6 @@ void main() { test('layers smoketest for rendering/custom_coordinate_systems.dart', () { FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; }; demo.main(); - expect(SchedulerBinding.instance!.hasScheduledFrame, true); + expect(SchedulerBinding.instance.hasScheduledFrame, true); }); } diff --git a/examples/layers/test/smoketests/rendering/flex_layout_test.dart b/examples/layers/test/smoketests/rendering/flex_layout_test.dart index 3c0580a9408..ebdb3660ec9 100644 --- a/examples/layers/test/smoketests/rendering/flex_layout_test.dart +++ b/examples/layers/test/smoketests/rendering/flex_layout_test.dart @@ -13,6 +13,6 @@ void main() { test('layers smoketest for rendering/flex_layout.dart', () { FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; }; demo.main(); - expect(SchedulerBinding.instance!.hasScheduledFrame, true); + expect(SchedulerBinding.instance.hasScheduledFrame, true); }); } diff --git a/examples/layers/test/smoketests/rendering/hello_world_test.dart b/examples/layers/test/smoketests/rendering/hello_world_test.dart index 0f3e085b52b..afd47994f7b 100644 --- a/examples/layers/test/smoketests/rendering/hello_world_test.dart +++ b/examples/layers/test/smoketests/rendering/hello_world_test.dart @@ -13,6 +13,6 @@ void main() { test('layers smoketest for rendering/hello_world.dart', () { FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; }; demo.main(); - expect(SchedulerBinding.instance!.hasScheduledFrame, true); + expect(SchedulerBinding.instance.hasScheduledFrame, true); }); } diff --git a/examples/layers/test/smoketests/rendering/spinning_square_test.dart b/examples/layers/test/smoketests/rendering/spinning_square_test.dart index 4d816071cf0..6954d25002d 100644 --- a/examples/layers/test/smoketests/rendering/spinning_square_test.dart +++ b/examples/layers/test/smoketests/rendering/spinning_square_test.dart @@ -13,6 +13,6 @@ void main() { test('layers smoketest for rendering/spinning_square.dart', () { FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; }; demo.main(); - expect(SchedulerBinding.instance!.hasScheduledFrame, true); + expect(SchedulerBinding.instance.hasScheduledFrame, true); }); } diff --git a/examples/layers/test/smoketests/rendering/touch_input_test.dart b/examples/layers/test/smoketests/rendering/touch_input_test.dart index b55df3aeb9b..0ebb9dd7620 100644 --- a/examples/layers/test/smoketests/rendering/touch_input_test.dart +++ b/examples/layers/test/smoketests/rendering/touch_input_test.dart @@ -13,6 +13,6 @@ void main() { test('layers smoketest for rendering/touch_input.dart', () { FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; }; demo.main(); - expect(SchedulerBinding.instance!.hasScheduledFrame, true); + expect(SchedulerBinding.instance.hasScheduledFrame, true); }); } diff --git a/examples/layers/widgets/spinning_mixed.dart b/examples/layers/widgets/spinning_mixed.dart index b2f007f72f6..d62f3c431c2 100644 --- a/examples/layers/widgets/spinning_mixed.dart +++ b/examples/layers/widgets/spinning_mixed.dart @@ -73,7 +73,7 @@ void attachWidgetTreeToRenderTree(RenderProxyBox container) { ), ), ), - ).attachToRenderTree(WidgetsBinding.instance!.buildOwner!, element); + ).attachToRenderTree(WidgetsBinding.instance.buildOwner!, element); } Duration? timeBase; @@ -86,7 +86,7 @@ void rotate(Duration timeStamp) { transformBox.setIdentity(); transformBox.rotateZ(delta); - WidgetsBinding.instance!.buildOwner!.buildScope(element!); + WidgetsBinding.instance.buildOwner!.buildScope(element!); } void main() { diff --git a/packages/flutter/lib/src/animation/animation_controller.dart b/packages/flutter/lib/src/animation/animation_controller.dart index 226f368b627..2da2b02fca1 100644 --- a/packages/flutter/lib/src/animation/animation_controller.dart +++ b/packages/flutter/lib/src/animation/animation_controller.dart @@ -567,7 +567,7 @@ class AnimationController extends Animation TickerFuture _animateToInternal(double target, { Duration? duration, Curve curve = Curves.linear }) { double scale = 1.0; - if (SemanticsBinding.instance!.disableAnimations) { + if (SemanticsBinding.instance.disableAnimations) { switch (animationBehavior) { case AnimationBehavior.normal: // Since the framework cannot handle zero duration animations, we run it at 5% of the normal @@ -688,7 +688,7 @@ class AnimationController extends Animation : upperBound + _kFlingTolerance.distance; double scale = 1.0; final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior; - if (SemanticsBinding.instance!.disableAnimations) { + if (SemanticsBinding.instance.disableAnimations) { switch (behavior) { case AnimationBehavior.normal: // TODO(jonahwilliams): determine a better process for setting velocity. diff --git a/packages/flutter/lib/src/cupertino/context_menu.dart b/packages/flutter/lib/src/cupertino/context_menu.dart index b4f2194ea65..009f609a338 100644 --- a/packages/flutter/lib/src/cupertino/context_menu.dart +++ b/packages/flutter/lib/src/cupertino/context_menu.dart @@ -315,7 +315,7 @@ class _CupertinoContextMenuState extends State with Ticker // because _ContextMenuRoute renders its first frame offscreen. // Otherwise there would be a visible flash when nothing is rendered for // one frame. - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _lastOverlayEntry?.remove(); _lastOverlayEntry = null; _openController.reset(); @@ -742,7 +742,7 @@ class _ContextMenuRoute extends PopupRoute { // Render one frame offstage in the final position so that we can take // measurements of its layout and then animate to them. - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _updateTweenRects(); _internalOffstage = false; _setOffstageInternally(); diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart index 86ff0f5a8d9..b2e722960d8 100644 --- a/packages/flutter/lib/src/cupertino/date_picker.dart +++ b/packages/flutter/lib/src/cupertino/date_picker.dart @@ -585,7 +585,7 @@ class _CupertinoDatePickerDateTimeState extends State { minuteController = FixedExtentScrollController(initialItem: initialDateTime.minute ~/ widget.minuteInterval); dateController = FixedExtentScrollController(initialItem: 0); - PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange); } void _handleSystemFontsChange () { @@ -604,7 +604,7 @@ class _CupertinoDatePickerDateTimeState extends State { minuteController.dispose(); meridiemController.dispose(); - PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange); super.dispose(); } @@ -930,7 +930,7 @@ class _CupertinoDatePickerDateTimeState extends State { void _scrollToDate(DateTime newDate, DateTime fromDate) { assert(newDate != null); - SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { if (fromDate.year != newDate.year || fromDate.month != newDate.month || fromDate.day != newDate.day) { _animateColumnControllerToItem(dateController, selectedDayFromInitial); } @@ -1104,7 +1104,7 @@ class _CupertinoDatePickerDateState extends State { monthController = FixedExtentScrollController(initialItem: selectedMonth - 1); yearController = FixedExtentScrollController(initialItem: selectedYear); - PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange); } void _handleSystemFontsChange() { @@ -1120,7 +1120,7 @@ class _CupertinoDatePickerDateState extends State { monthController.dispose(); yearController.dispose(); - PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange); super.dispose(); } @@ -1326,7 +1326,7 @@ class _CupertinoDatePickerDateState extends State { void _scrollToDate(DateTime newDate) { assert(newDate != null); - SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { if (selectedYear != newDate.year) { _animateColumnControllerToItem(yearController, newDate.year); } @@ -1608,7 +1608,7 @@ class _CupertinoTimerPickerState extends State { if (widget.mode != CupertinoTimerPickerMode.hm) selectedSecond = widget.initialTimerDuration.inSeconds % 60; - PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange); } void _handleSystemFontsChange() { @@ -1621,7 +1621,7 @@ class _CupertinoTimerPickerState extends State { @override void dispose() { - PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange); super.dispose(); } diff --git a/packages/flutter/lib/src/cupertino/refresh.dart b/packages/flutter/lib/src/cupertino/refresh.dart index 29a69e03656..b4018f2bc76 100644 --- a/packages/flutter/lib/src/cupertino/refresh.dart +++ b/packages/flutter/lib/src/cupertino/refresh.dart @@ -506,10 +506,10 @@ class _CupertinoSliverRefreshControlState extends State hasSliverLayoutExtent = false); } else { - SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { setState(() => hasSliverLayoutExtent = false); }); } @@ -535,7 +535,7 @@ class _CupertinoSliverRefreshControlState extends State refreshTask = null); diff --git a/packages/flutter/lib/src/foundation/README.md b/packages/flutter/lib/src/foundation/README.md index c37e4f0e9b1..8f62a9b84de 100644 --- a/packages/flutter/lib/src/foundation/README.md +++ b/packages/flutter/lib/src/foundation/README.md @@ -7,6 +7,11 @@ Currently they do depend on dart:ui, but only for `VoidCallback` and `hashValues` (and maybe one day `hashList` and `lerpDouble`), which are all intended to be moved out of `dart:ui` and into `dart:core`. +There is currently also an unfortunate dependency on the platform +dispatcher logic (SingletonFlutterWindow, Brightness, +PlatformDispatcher, window), though that should probably move to the +'services' library. + See also: * https://github.com/dart-lang/sdk/issues/27791 (`VoidCallback`) diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart index e89d25056d9..904d393e79d 100644 --- a/packages/flutter/lib/src/foundation/binding.dart +++ b/packages/flutter/lib/src/foundation/binding.dart @@ -14,10 +14,14 @@ import 'assertions.dart'; import 'basic_types.dart'; import 'constants.dart'; import 'debug.dart'; +import 'diagnostics.dart'; import 'object.dart'; import 'platform.dart'; import 'print.dart'; +// Examples can assume: +// mixin BarBinding on BindingBase { } + /// Signature for service extensions. /// /// The returned map must not contain the keys "type" or "method", as @@ -27,21 +31,101 @@ import 'print.dart'; /// "method" key will be set to the full name of the method. typedef ServiceExtensionCallback = Future> Function(Map parameters); -/// Base class for mixins that provide singleton services (also known as -/// "bindings"). +/// Base class for mixins that provide singleton services. /// -/// To use this class in an `on` clause of a mixin, inherit from it and implement -/// [initInstances()]. The mixin is guaranteed to only be constructed once in -/// the lifetime of the app (more precisely, it will assert if constructed twice -/// in checked mode). +/// The Flutter engine ([dart:ui]) exposes some low-level services, +/// but these are typically not suitable for direct use, for example +/// because they only provide a single callback which an application +/// may wish to multiplex to allow multiple listeners. /// -/// The top-most layer used to write the application will have a concrete class -/// that inherits from [BindingBase] and uses all the various [BindingBase] -/// mixins (such as [ServicesBinding]). For example, the Widgets library in -/// Flutter introduces a binding called [WidgetsFlutterBinding]. The relevant -/// library defines how to create the binding. It could be implied (for example, -/// [WidgetsFlutterBinding] is automatically started from [runApp]), or the -/// application might be required to explicitly call the constructor. +/// Bindings provide the glue between these low-level APIs and the +/// higher-level framework APIs. They _bind_ the two together, whence +/// the name. +/// +/// ## Implementing a binding mixin +/// +/// A library would typically create a new binding mixin to expose a +/// feature in [dart:ui]. This is rare in general, but it is something +/// that an alternative framework would do, e.g. if a framework were +/// to replace the [widgets] library with an alternative API but still +/// wished to leverage the [services] and [foundation] libraries. +/// +/// To create a binding mixin, declare a mixin `on` the [BindingBase] class +/// and whatever other bindings the concrete binding must implement for +/// this binding mixin to be useful. +/// +/// The mixin is guaranteed to only be constructed once in the +/// lifetime of the app; this is handled by [initInstances]. +/// +/// A binding mixin must at a minimum implement the following features: +/// +/// * The [initInstances] method, which must call `super.initInstances` and +/// set an `_instance` static field to `this`. +/// * An `instance` static getter, which must return that field using [checkInstance]. +/// +/// In addition, it should implement whatever singleton features the library needs. +/// +/// As a general rule, the less can be placed in the binding, the +/// better. Prefer having APIs that takes objects rather than having +/// them refer to global singletons. Bindings are best limited to +/// exposing features that literally only exist once, for example, the +/// APIs in [dart:ui]. +/// +/// {@tool snippet} +/// +/// Here is a basic example of a binding that implements these features. It relies on +/// another fictional binding called `BarBinding`. +/// +/// ```dart +/// mixin FooBinding on BindingBase, BarBinding { +/// @override +/// void initInstances() { +/// super.initInstances(); +/// _instance = this; +/// // ...binding initialization... +/// } +/// +/// static FooBinding get instance => BindingBase.checkInstance(_instance); +/// static FooBinding? _instance; +/// +/// // ...binding features... +/// } +/// ``` +/// {@end-tool} +/// +/// ## Implementing a binding class +/// +/// The top-most layer used to write the application (e.g. the Flutter +/// [widgets] library) will have a concrete class that inherits from +/// [BindingBase] and uses all the various [BindingBase] mixins (such +/// as [ServicesBinding]). The [widgets] library in Flutter introduces +/// a binding called [WidgetsFlutterBinding]. +/// +/// A binding _class_ should mix in the relevant bindings from each +/// layer that it wishes to expose, and should have an +/// `ensureInitialized` method that constructs the class if that +/// layer's mixin's `_instance` field is null. This allows the binding +/// to be overriden by developers who have more specific needs, while +/// still allowing other code to call `ensureInitialized` when a binding +/// is needed. +/// +/// {@tool snippet} +/// +/// A typical binding class is shown below. The `ensureInitialized` method's +/// return type is the library's binding mixin, rather than the concrete +/// class. +/// +/// ```dart +/// class FooLibraryBinding extends BindingBase with BarBinding, FooBinding { +/// static FooBinding ensureInitialized() { +/// if (FooBinding._instance == null) { +/// FooLibraryBinding(); +/// } +/// return FooBinding.instance; +/// } +/// } +/// /// ``` +/// {@end-tool} abstract class BindingBase { /// Default abstract constructor for bindings. /// @@ -51,6 +135,10 @@ abstract class BindingBase { /// observatory service extensions, if any. BindingBase() { developer.Timeline.startSync('Framework initialization'); + assert(() { + _debugConstructed = true; + return true; + }()); assert(!_debugInitialized); initInstances(); @@ -65,6 +153,7 @@ abstract class BindingBase { developer.Timeline.finishSync(); } + bool _debugConstructed = false; static bool _debugInitialized = false; static bool _debugServiceExtensionsRegistered = false; @@ -131,10 +220,39 @@ abstract class BindingBase { /// the platform and otherwise configure their services. Subclasses must call /// "super.initInstances()". /// - /// By convention, if the service is to be provided as a singleton, it should - /// be exposed as `MixinClassName.instance`, a static getter that returns + /// The binding is not fully initialized when this method runs (for + /// example, other binding mixins may not yet have run their + /// [initInstances] method). For this reason, code in this method + /// should avoid invoking callbacks or synchronously triggering any + /// code that would normally assume that the bindings are ready. + /// + /// {@tool snippet} + /// + /// By convention, if the service is to be provided as a singleton, + /// it should be exposed as `MixinClassName.instance`, a static + /// getter with a non-nullable return type that returns /// `MixinClassName._instance`, a static field that is set by - /// `initInstances()`. + /// `initInstances()`. To improve the developer experience, the + /// return value should actually be + /// `BindingBase.checkInstance(_instance)` (see [checkInstance]), as + /// in the example below. + /// + /// ```dart + /// mixin BazBinding on BindingBase { + /// @override + /// void initInstances() { + /// super.initInstances(); + /// _instance = this; + /// // ...binding initialization... + /// } + /// + /// static BazBinding get instance => BindingBase.checkInstance(_instance); + /// static BazBinding? _instance; + /// + /// // ...binding features... + /// } + /// ``` + /// {@end-tool} @protected @mustCallSuper void initInstances() { @@ -145,6 +263,100 @@ abstract class BindingBase { }()); } + /// A method that shows a useful error message if the given binding + /// instance is not initialized. + /// + /// See [initInstances] for advice on using this method. + /// + /// This method either returns the argument or throws an exception. + /// In release mode it always returns the argument. + /// + /// The type argument `T` should be the kind of binding mixin (e.g. + /// `SchedulerBinding`) that is calling the method. It is used in + /// error messages. + @protected + static T checkInstance(T? instance) { + assert(() { + if (!_debugInitialized && instance == null) { + throw FlutterError.fromParts([ + ErrorSummary('Binding has not yet been initialized.'), + ErrorDescription('The "instance" getter on the $T binding mixin is only available once that binding has been initialized.'), + ErrorHint( + 'Typically, this is done by calling "WidgetsFlutterBinding.ensureInitialized()" or "runApp()" (the ' + 'latter calls the former). Typically this call is done in the "void main()" method. The "ensureInitialized" method ' + 'is idempotent; calling it multiple times is not harmful. After calling that method, the "instance" getter will ' + 'return the binding.', + ), + ErrorHint( + 'In a test, one can call "TestWidgetsFlutterBinding.ensureInitialized()" as the first line in the test\'s "main()" method ' + 'to initialize the binding.', + ), + ErrorHint( + 'If $T is a custom binding mixin, there must also be a custom binding class, like WidgetsFlutterBinding, ' + 'but that mixes in the selected binding, and that is the class that must be constructed before using the "instance" getter.', + ), + ]); + } + if (instance == null) { + assert(_debugInitialized); + throw FlutterError.fromParts([ + ErrorSummary('Binding mixin instance is null but bindings are already initialized.'), + ErrorDescription( + 'The "instance" property of the $T binding mixin was accessed, but that binding was not initialized when ' + 'the "initInstances()" method was called.' + ), + ErrorHint( + 'This probably indicates that the $T mixin was not mixed into the class that was used to initialize the binding. ' + 'If this is a custom binding mixin, there must also be a custom binding class, like WidgetsFlutterBinding, ' + 'but that mixes in the selected binding. If this is a test binding, check that the binding being initialized ' + 'is the same as the one into which the test binding is mixed.' + ), + ]); + } + try { + assert(instance != null); + if (instance._debugConstructed && !_debugInitialized) { + throw FlutterError.fromParts([ + ErrorSummary('Binding initialized without calling initInstances.'), + ErrorDescription('An instance of $T is non-null, but BindingBase.initInstances() has not yet been called.'), + ErrorHint( + 'This could happen because a binding mixin was somehow used outside of the normal binding mechanisms, or because ' + 'the binding\'s initInstances() method did not call "super.initInstances()".' + ), + ErrorHint( + 'This could also happen if some code was invoked that used the binding while the binding was initializing, ' + 'for example if the "initInstances" method invokes a callback. Bindings should not invoke callbacks before ' + '"initInstances" has completed.' + ), + ]); + } + if (!instance._debugConstructed) { + // The state of _debugInitialized doesn't matter in this failure mode. + throw FlutterError.fromParts([ + ErrorSummary('Binding did not complete initialization.'), + ErrorDescription('An instance of $T is non-null, but the BindingBase() constructor has not yet been called.'), + ErrorHint( + 'This could also happen if some code was invoked that used the binding while the binding was initializing, ' + "for example if the binding's constructor itself invokes a callback. Bindings should not invoke callbacks " + 'before "initInstances" has completed.' + ), + ]); + } + } on NoSuchMethodError { + throw FlutterError.fromParts([ + ErrorSummary('Binding does not extend BindingBase'), + ErrorDescription('An instance of $T was created but the BindingBase constructor was not called.'), + ErrorHint( + 'This could happen because the binding was implemented using "implements" rather than "extends" or "with". ' + 'Concrete binding classes must extend or mix in BindingBase.' + ), + ]); + } + return true; + }()); + return instance!; + } + /// Called when the binding is initialized, to register service /// extensions. /// @@ -555,7 +767,7 @@ abstract class BindingBase { /// available in debug and profile mode. /// /// ```dart - /// void myRegistrationFunction() { + /// void myOtherRegistrationFunction() { /// // kReleaseMode is defined in the 'flutter/foundation.dart' package. /// if (!kReleaseMode) { /// // Register your service extension here. diff --git a/packages/flutter/lib/src/gestures/binding.dart b/packages/flutter/lib/src/gestures/binding.dart index 3689aef4502..93a269db67f 100644 --- a/packages/flutter/lib/src/gestures/binding.dart +++ b/packages/flutter/lib/src/gestures/binding.dart @@ -73,7 +73,7 @@ class _Resampler { // Add `event` for resampling or dispatch it directly if // not a touch event. void addOrDispatch(PointerEvent event) { - final SchedulerBinding? scheduler = SchedulerBinding.instance; + final SchedulerBinding scheduler = SchedulerBinding.instance; assert(scheduler != null); // Add touch event to resampler or dispatch pointer event directly. if (event.kind == PointerDeviceKind.touch) { @@ -94,9 +94,10 @@ class _Resampler { // // The `samplingOffset` is relative to the current frame time, which // can be in the past when we're not actively resampling. + // // The `samplingClock` is the clock used to determine frame time age. void sample(Duration samplingOffset, SamplingClock clock) { - final SchedulerBinding? scheduler = SchedulerBinding.instance; + final SchedulerBinding scheduler = SchedulerBinding.instance; assert(scheduler != null); // Initialize `_frameTime` if needed. This will be used for periodic @@ -156,7 +157,7 @@ class _Resampler { // Add a post frame callback as this avoids producing unnecessary // frames but ensures that sampling phase is adjusted to frame // time when frames are produced. - scheduler?.addPostFrameCallback((_) { + scheduler.addPostFrameCallback((_) { _frameCallbackScheduled = false; // We use `currentSystemFrameTimeStamp` here as it's critical that // sample time is in the same clock as the event time stamps, and @@ -259,16 +260,20 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H window.onPointerDataPacket = _handlePointerDataPacket; } + /// The singleton instance of this object. + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static GestureBinding get instance => BindingBase.checkInstance(_instance); + static GestureBinding? _instance; + @override void unlocked() { super.unlocked(); _flushPointerEventQueue(); } - /// The singleton instance of this object. - static GestureBinding? get instance => _instance; - static GestureBinding? _instance; - final Queue _pendingPointerEvents = Queue(); void _handlePointerDataPacket(ui.PointerDataPacket packet) { diff --git a/packages/flutter/lib/src/gestures/multidrag.dart b/packages/flutter/lib/src/gestures/multidrag.dart index 281eb1595f6..9f60dec8e6f 100644 --- a/packages/flutter/lib/src/gestures/multidrag.dart +++ b/packages/flutter/lib/src/gestures/multidrag.dart @@ -231,8 +231,8 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer { assert(!_pointers!.containsKey(event.pointer)); final MultiDragPointerState state = createNewPointerState(event); _pointers![event.pointer] = state; - GestureBinding.instance!.pointerRouter.addRoute(event.pointer, _handleEvent); - state._setArenaEntry(GestureBinding.instance!.gestureArena.add(event.pointer, this)); + GestureBinding.instance.pointerRouter.addRoute(event.pointer, _handleEvent); + state._setArenaEntry(GestureBinding.instance.gestureArena.add(event.pointer, this)); } /// Subclasses should override this method to create per-pointer state @@ -312,7 +312,7 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer { return; } assert(_pointers!.containsKey(pointer)); - GestureBinding.instance!.pointerRouter.removeRoute(pointer, _handleEvent); + GestureBinding.instance.pointerRouter.removeRoute(pointer, _handleEvent); _pointers!.remove(pointer)!.dispose(); } diff --git a/packages/flutter/lib/src/gestures/multitap.dart b/packages/flutter/lib/src/gestures/multitap.dart index 83abd2da03e..295192603dd 100644 --- a/packages/flutter/lib/src/gestures/multitap.dart +++ b/packages/flutter/lib/src/gestures/multitap.dart @@ -79,14 +79,14 @@ class _TapTracker { void startTrackingPointer(PointerRoute route, Matrix4? transform) { if (!_isTrackingPointer) { _isTrackingPointer = true; - GestureBinding.instance!.pointerRouter.addRoute(pointer, route, transform); + GestureBinding.instance.pointerRouter.addRoute(pointer, route, transform); } } void stopTrackingPointer(PointerRoute route) { if (_isTrackingPointer) { _isTrackingPointer = false; - GestureBinding.instance!.pointerRouter.removeRoute(pointer, route); + GestureBinding.instance.pointerRouter.removeRoute(pointer, route); } } @@ -242,7 +242,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { _stopDoubleTapTimer(); final _TapTracker tracker = _TapTracker( event: event, - entry: GestureBinding.instance!.gestureArena.add(event.pointer, this), + entry: GestureBinding.instance.gestureArena.add(event.pointer, this), doubleTapMinTime: kDoubleTapMinTime, ); _trackers[event.pointer] = tracker; @@ -311,14 +311,14 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { final _TapTracker tracker = _firstTap!; _firstTap = null; _reject(tracker); - GestureBinding.instance!.gestureArena.release(tracker.pointer); + GestureBinding.instance.gestureArena.release(tracker.pointer); } _clearTrackers(); } void _registerFirstTap(_TapTracker tracker) { _startDoubleTapTimer(); - GestureBinding.instance!.gestureArena.hold(tracker.pointer); + GestureBinding.instance.gestureArena.hold(tracker.pointer); // Note, order is important below in order for the clear -> reject logic to // work properly. _freezeTracker(tracker); @@ -383,7 +383,7 @@ class _TapGesture extends _TapTracker { }) : _lastPosition = OffsetPair.fromEventPosition(event), super( event: event as PointerDownEvent, - entry: GestureBinding.instance!.gestureArena.add(event.pointer, gestureRecognizer), + entry: GestureBinding.instance.gestureArena.add(event.pointer, gestureRecognizer), doubleTapMinTime: kDoubleTapMinTime, ) { startTrackingPointer(handleEvent, event.transform); diff --git a/packages/flutter/lib/src/gestures/pointer_signal_resolver.dart b/packages/flutter/lib/src/gestures/pointer_signal_resolver.dart index 0208060da3d..d4c791cc34d 100644 --- a/packages/flutter/lib/src/gestures/pointer_signal_resolver.dart +++ b/packages/flutter/lib/src/gestures/pointer_signal_resolver.dart @@ -30,7 +30,7 @@ bool _isSameEvent(PointerSignalEvent event1, PointerSignalEvent event2) { /// /// ```dart /// void handleSignalEvent(PointerSignalEvent event) { -/// GestureBinding.instance!.pointerSignalResolver.register(event, (PointerSignalEvent event) { +/// GestureBinding.instance.pointerSignalResolver.register(event, (PointerSignalEvent event) { /// // handle the event... /// }); /// } @@ -96,7 +96,7 @@ bool _isSameEvent(PointerSignalEvent event1, PointerSignalEvent event2) { /// child: Listener( /// onPointerSignal: (PointerSignalEvent event) { /// if (widget.useResolver) { -/// GestureBinding.instance!.pointerSignalResolver.register(event, (PointerSignalEvent event) { +/// GestureBinding.instance.pointerSignalResolver.register(event, (PointerSignalEvent event) { /// rotateColor(); /// }); /// } else { diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index b890b89a0b1..0f839fce1a6 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -317,7 +317,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { void dispose() { resolve(GestureDisposition.rejected); for (final int pointer in _trackedPointers) - GestureBinding.instance!.pointerRouter.removeRoute(pointer, handleEvent); + GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); _trackedPointers.clear(); assert(_entries.isEmpty); super.dispose(); @@ -347,7 +347,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { GestureArenaEntry _addPointerToArena(int pointer) { if (_team != null) return _team!.add(pointer, this); - return GestureBinding.instance!.gestureArena.add(pointer, this); + return GestureBinding.instance.gestureArena.add(pointer, this); } /// Causes events related to the given pointer ID to be routed to this recognizer. @@ -366,7 +366,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { /// This is called by [OneSequenceGestureRecognizer.addAllowedPointer]. @protected void startTrackingPointer(int pointer, [Matrix4? transform]) { - GestureBinding.instance!.pointerRouter.addRoute(pointer, handleEvent, transform); + GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform); _trackedPointers.add(pointer); assert(!_entries.containsValue(pointer)); _entries[pointer] = _addPointerToArena(pointer); @@ -381,7 +381,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { @protected void stopTrackingPointer(int pointer) { if (_trackedPointers.contains(pointer)) { - GestureBinding.instance!.pointerRouter.removeRoute(pointer, handleEvent); + GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); _trackedPointers.remove(pointer); if (_trackedPointers.isEmpty) didStopTrackingLastPointer(pointer); diff --git a/packages/flutter/lib/src/gestures/team.dart b/packages/flutter/lib/src/gestures/team.dart index e2eee5573a8..95d828d7135 100644 --- a/packages/flutter/lib/src/gestures/team.dart +++ b/packages/flutter/lib/src/gestures/team.dart @@ -61,7 +61,7 @@ class _CombiningGestureArenaMember extends GestureArenaMember { assert(!_resolved); assert(_pointer == pointer); _members.add(member); - _entry ??= GestureBinding.instance!.gestureArena.add(pointer, this); + _entry ??= GestureBinding.instance.gestureArena.add(pointer, this); return _CombiningGestureArenaEntry(this, member); } diff --git a/packages/flutter/lib/src/material/about.dart b/packages/flutter/lib/src/material/about.dart index 3129e97ebd9..cdbfa88f82e 100644 --- a/packages/flutter/lib/src/material/about.dart +++ b/packages/flutter/lib/src/material/about.dart @@ -844,7 +844,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> { return true; }()); final List paragraphs = - await SchedulerBinding.instance!.scheduleTask>( + await SchedulerBinding.instance.scheduleTask>( license.paragraphs.toList, Priority.animation, debugLabel: 'License', @@ -1507,15 +1507,13 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold> @override void openDetailPage(Object arguments) { - SchedulerBinding.instance! - .addPostFrameCallback((_) => _detailArguments.value = arguments); + SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments); _MasterDetailFlow.of(context)!.openDetailPage(arguments); } @override void setInitialDetailPage(Object arguments) { - SchedulerBinding.instance! - .addPostFrameCallback((_) => _detailArguments.value = arguments); + SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments); _MasterDetailFlow.of(context)!.setInitialDetailPage(arguments); } diff --git a/packages/flutter/lib/src/material/autocomplete.dart b/packages/flutter/lib/src/material/autocomplete.dart index 19b0d5e7c22..60801d524a8 100644 --- a/packages/flutter/lib/src/material/autocomplete.dart +++ b/packages/flutter/lib/src/material/autocomplete.dart @@ -301,7 +301,7 @@ class _AutocompleteOptions extends StatelessWidget { builder: (BuildContext context) { final bool highlight = AutocompleteHighlightedOption.of(context) == index; if (highlight) { - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { Scrollable.ensureVisible(context, alignment: 0.5); }); } diff --git a/packages/flutter/lib/src/material/calendar_date_picker.dart b/packages/flutter/lib/src/material/calendar_date_picker.dart index 829a271b4f2..d1c1fc33084 100644 --- a/packages/flutter/lib/src/material/calendar_date_picker.dart +++ b/packages/flutter/lib/src/material/calendar_date_picker.dart @@ -533,7 +533,7 @@ class _MonthPickerState extends State<_MonthPicker> { super.didUpdateWidget(oldWidget); if (widget.initialMonth != oldWidget.initialMonth && widget.initialMonth != _currentMonth) { // We can't interrupt this widget build with a scroll, so do it next frame - WidgetsBinding.instance!.addPostFrameCallback( + WidgetsBinding.instance.addPostFrameCallback( (Duration timeStamp) => _showMonth(widget.initialMonth, jump: true), ); } diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index edf34fb4d8e..91a1b48dd8f 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -1237,16 +1237,16 @@ class _DropdownButtonState extends State> with WidgetsBindi ), }; focusNode!.addListener(_handleFocusChanged); - final FocusManager focusManager = WidgetsBinding.instance!.focusManager; + final FocusManager focusManager = WidgetsBinding.instance.focusManager; _focusHighlightMode = focusManager.highlightMode; focusManager.addHighlightModeListener(_handleFocusHighlightModeChange); } @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _removeDropdownRoute(); - WidgetsBinding.instance!.focusManager.removeHighlightModeListener(_handleFocusHighlightModeChange); + WidgetsBinding.instance.focusManager.removeHighlightModeListener(_handleFocusHighlightModeChange); focusNode!.removeListener(_handleFocusChanged); _internalNode?.dispose(); super.dispose(); diff --git a/packages/flutter/lib/src/material/input_date_picker_form_field.dart b/packages/flutter/lib/src/material/input_date_picker_form_field.dart index 93f8ee84e08..d61a60b66cb 100644 --- a/packages/flutter/lib/src/material/input_date_picker_form_field.dart +++ b/packages/flutter/lib/src/material/input_date_picker_form_field.dart @@ -161,7 +161,7 @@ class _InputDatePickerFormFieldState extends State { super.didUpdateWidget(oldWidget); if (widget.initialDate != oldWidget.initialDate) { // Can't update the form field in the middle of a build, so do it next frame - WidgetsBinding.instance!.addPostFrameCallback((Duration timeStamp) { + WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { setState(() { _selectedDate = widget.initialDate; _updateValueForSelectedDate(); diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index e36cdfcf190..f56dd6f1813 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -833,7 +833,7 @@ class _DialPainter extends CustomPainter { required this.theta, required this.textDirection, required this.selectedValue, - }) : super(repaint: PaintingBinding.instance!.systemFonts); + }) : super(repaint: PaintingBinding.instance.systemFonts); final List<_TappableLabel> primaryLabels; final List<_TappableLabel> secondaryLabels; diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index 03dbb59db04..92c396abc6d 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -269,7 +269,7 @@ class _TooltipState extends State with SingleTickerProviderStateMixin { @override void initState() { super.initState(); - _mouseIsConnected = RendererBinding.instance!.mouseTracker.mouseIsConnected; + _mouseIsConnected = RendererBinding.instance.mouseTracker.mouseIsConnected; _controller = AnimationController( duration: _fadeInDuration, reverseDuration: _fadeOutDuration, @@ -277,10 +277,10 @@ class _TooltipState extends State with SingleTickerProviderStateMixin { ) ..addStatusListener(_handleStatusChanged); // Listen to see when a mouse is added. - RendererBinding.instance!.mouseTracker.addListener(_handleMouseTrackerChange); + RendererBinding.instance.mouseTracker.addListener(_handleMouseTrackerChange); // Listen to global pointer events so that we can hide a tooltip immediately // if some other control is clicked on. - GestureBinding.instance!.pointerRouter.addGlobalRoute(_handlePointerEvent); + GestureBinding.instance.pointerRouter.addGlobalRoute(_handlePointerEvent); } // https://material.io/components/tooltips#specs @@ -325,7 +325,7 @@ class _TooltipState extends State with SingleTickerProviderStateMixin { if (!mounted) { return; } - final bool mouseIsConnected = RendererBinding.instance!.mouseTracker.mouseIsConnected; + final bool mouseIsConnected = RendererBinding.instance.mouseTracker.mouseIsConnected; if (mouseIsConnected != _mouseIsConnected) { setState(() { _mouseIsConnected = mouseIsConnected; @@ -456,8 +456,8 @@ class _TooltipState extends State with SingleTickerProviderStateMixin { @override void dispose() { - GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handlePointerEvent); - RendererBinding.instance!.mouseTracker.removeListener(_handleMouseTrackerChange); + GestureBinding.instance.pointerRouter.removeGlobalRoute(_handlePointerEvent); + RendererBinding.instance.mouseTracker.removeListener(_handleMouseTrackerChange); _removeEntry(); _controller.dispose(); super.dispose(); diff --git a/packages/flutter/lib/src/painting/_network_image_io.dart b/packages/flutter/lib/src/painting/_network_image_io.dart index fb485ce2eac..dd18497e9ab 100644 --- a/packages/flutter/lib/src/painting/_network_image_io.dart +++ b/packages/flutter/lib/src/painting/_network_image_io.dart @@ -118,7 +118,7 @@ class NetworkImage extends image_provider.ImageProvider _instance; + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static PaintingBinding get instance => BindingBase.checkInstance(_instance); static PaintingBinding? _instance; /// [ShaderWarmUp] instance to be executed during [initInstances]. @@ -67,8 +70,8 @@ mixin PaintingBinding on BindingBase, ServicesBinding { /// /// The image cache is created during startup by the [createImageCache] /// method. - ImageCache? get imageCache => _imageCache; - ImageCache? _imageCache; + ImageCache get imageCache => _imageCache; + late ImageCache _imageCache; /// Creates the [ImageCache] singleton (accessible via [imageCache]). /// @@ -114,14 +117,14 @@ mixin PaintingBinding on BindingBase, ServicesBinding { @override void evict(String asset) { super.evict(asset); - imageCache!.clear(); - imageCache!.clearLiveImages(); + imageCache.clear(); + imageCache.clearLiveImages(); } @override void handleMemoryPressure() { super.handleMemoryPressure(); - imageCache?.clear(); + imageCache.clear(); } /// Listenable that notifies when the available fonts on the system have @@ -176,4 +179,4 @@ class _SystemFontsNotifier extends Listenable { /// /// The image cache is created during startup by the [PaintingBinding]'s /// [PaintingBinding.createImageCache] method. -ImageCache? get imageCache => PaintingBinding.instance!.imageCache; +ImageCache get imageCache => PaintingBinding.instance.imageCache; diff --git a/packages/flutter/lib/src/painting/decoration_image.dart b/packages/flutter/lib/src/painting/decoration_image.dart index a7b16000719..73f8360d400 100644 --- a/packages/flutter/lib/src/painting/decoration_image.dart +++ b/packages/flutter/lib/src/painting/decoration_image.dart @@ -539,7 +539,7 @@ void paintImage({ _pendingImageSizeInfo[sizeInfo.source!] = sizeInfo; } debugOnPaintImage?.call(sizeInfo); - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { _lastFrameImageSizeInfo = _pendingImageSizeInfo.values.toSet(); if (_pendingImageSizeInfo.isEmpty) { return; diff --git a/packages/flutter/lib/src/painting/image_cache.dart b/packages/flutter/lib/src/painting/image_cache.dart index f1e1906915b..8a9c8965bc4 100644 --- a/packages/flutter/lib/src/painting/image_cache.dart +++ b/packages/flutter/lib/src/painting/image_cache.dart @@ -622,7 +622,7 @@ abstract class _CachedImageBase { assert(handle != null); // Give any interested parties a chance to listen to the stream before we // potentially dispose it. - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { assert(handle != null); handle?.dispose(); handle = null; diff --git a/packages/flutter/lib/src/painting/image_decoder.dart b/packages/flutter/lib/src/painting/image_decoder.dart index 48e7e403bc6..b748c79fc9c 100644 --- a/packages/flutter/lib/src/painting/image_decoder.dart +++ b/packages/flutter/lib/src/painting/image_decoder.dart @@ -21,7 +21,7 @@ import 'binding.dart'; /// [PaintingBinding.instantiateImageCodec], and therefore can be mocked in /// tests. Future decodeImageFromList(Uint8List bytes) async { - final ui.Codec codec = await PaintingBinding.instance!.instantiateImageCodec(bytes); + final ui.Codec codec = await PaintingBinding.instance.instantiateImageCodec(bytes); final ui.FrameInfo frameInfo = await codec.getNextFrame(); return frameInfo.image; } diff --git a/packages/flutter/lib/src/painting/image_provider.dart b/packages/flutter/lib/src/painting/image_provider.dart index 852db6960b4..d09abed2611 100644 --- a/packages/flutter/lib/src/painting/image_provider.dart +++ b/packages/flutter/lib/src/painting/image_provider.dart @@ -387,7 +387,7 @@ abstract class ImageProvider { _createErrorHandlerAndKey( configuration, (T key, ImageErrorListener innerHandleError) { - completer.complete(PaintingBinding.instance!.imageCache!.statusForKey(key)); + completer.complete(PaintingBinding.instance.imageCache.statusForKey(key)); }, (T? key, Object exception, StackTrace? stack) async { if (handleError != null) { @@ -492,7 +492,7 @@ abstract class ImageProvider { // the image we want before getting to this method. We should avoid calling // load again, but still update the image cache with LRU information. if (stream.completer != null) { - final ImageStreamCompleter? completer = PaintingBinding.instance!.imageCache!.putIfAbsent( + final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent( key, () => stream.completer!, onError: handleError, @@ -500,9 +500,9 @@ abstract class ImageProvider { assert(identical(completer, stream.completer)); return; } - final ImageStreamCompleter? completer = PaintingBinding.instance!.imageCache!.putIfAbsent( + final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent( key, - () => load(key, PaintingBinding.instance!.instantiateImageCodec), + () => load(key, PaintingBinding.instance.instantiateImageCodec), onError: handleError, ); if (completer != null) { @@ -557,7 +557,7 @@ abstract class ImageProvider { Future evict({ ImageCache? cache, ImageConfiguration configuration = ImageConfiguration.empty }) async { cache ??= imageCache; final T key = await obtainKey(configuration); - return cache!.evict(key); + return cache.evict(key); } /// Converts an ImageProvider's settings plus an ImageConfiguration to a key @@ -674,11 +674,11 @@ abstract class AssetBundleImageProvider extends ImageProvider { if (bytes.lengthInBytes == 0) { // The file may become available later. - PaintingBinding.instance!.imageCache!.evict(key); + PaintingBinding.instance.imageCache.evict(key); throw StateError('$file is empty and cannot be loaded as an image.'); } diff --git a/packages/flutter/lib/src/painting/image_stream.dart b/packages/flutter/lib/src/painting/image_stream.dart index d91a50f34ff..2a6c8101439 100644 --- a/packages/flutter/lib/src/painting/image_stream.dart +++ b/packages/flutter/lib/src/painting/image_stream.dart @@ -964,7 +964,7 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter { return; } _frameCallbackScheduled = true; - SchedulerBinding.instance!.scheduleFrameCallback(_handleAppFrame); + SchedulerBinding.instance.scheduleFrameCallback(_handleAppFrame); } void _emitFrame(ImageInfo imageInfo) { diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 5c21c880e52..dd7fefcc60e 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -49,7 +49,11 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture } /// The current [RendererBinding], if one has been created. - static RendererBinding? get instance => _instance; + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static RendererBinding get instance => BindingBase.checkInstance(_instance); static RendererBinding? _instance; @override @@ -114,7 +118,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture registerServiceExtension( name: 'debugDumpLayerTree', callback: (Map parameters) async { - final String data = RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.'; + final String data = RendererBinding.instance.renderView.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.'; return { 'data': data, }; @@ -128,7 +132,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture registerServiceExtension( name: 'debugDumpRenderTree', callback: (Map parameters) async { - final String data = RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.'; + final String data = RendererBinding.instance.renderView.toStringDeep(); return { 'data': data, }; @@ -138,7 +142,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture registerServiceExtension( name: 'debugDumpSemanticsTreeInTraversalOrder', callback: (Map parameters) async { - final String data = RendererBinding.instance?.renderView.debugSemantics + final String data = RendererBinding.instance.renderView.debugSemantics ?.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversalOrder) ?? 'Semantics not collected.'; return { 'data': data, @@ -149,7 +153,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture registerServiceExtension( name: 'debugDumpSemanticsTreeInInverseHitTestOrder', callback: (Map parameters) async { - final String data = RendererBinding.instance?.renderView.debugSemantics + final String data = RendererBinding.instance.renderView.debugSemantics ?.toStringDeep(childOrder: DebugSemanticsDumpOrder.inverseHitTest) ?? 'Semantics not collected.'; return { 'data': data, @@ -229,7 +233,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture /// Querying [PlatformDispatcher.platformBrightness]. /// /// ```dart - /// final Brightness brightness = WidgetsBinding.instance!.platformDispatcher.platformBrightness; + /// final Brightness brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; /// ``` /// {@end-tool} /// @@ -338,7 +342,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture _debugMouseTrackerUpdateScheduled = true; return true; }()); - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { assert(_debugMouseTrackerUpdateScheduled); assert(() { _debugMouseTrackerUpdateScheduled = false; @@ -501,19 +505,19 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture child.markNeedsPaint(); child.visitChildren(visitor); }; - instance?.renderView.visitChildren(visitor); + instance.renderView.visitChildren(visitor); return endOfFrame; } } /// Prints a textual representation of the entire render tree. void debugDumpRenderTree() { - debugPrint(RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.'); + debugPrint(RendererBinding.instance.renderView.toStringDeep()); } /// Prints a textual representation of the entire layer tree. void debugDumpLayerTree() { - debugPrint(RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.'); + debugPrint(RendererBinding.instance.renderView.debugLayer?.toStringDeep()); } /// Prints a textual representation of the entire semantics tree. @@ -523,16 +527,27 @@ void debugDumpLayerTree() { /// The order in which the children of a [SemanticsNode] will be printed is /// controlled by the [childOrder] parameter. void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) { - debugPrint(RendererBinding.instance?.renderView.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.'); + debugPrint(RendererBinding.instance.renderView.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.'); } /// A concrete binding for applications that use the Rendering framework /// directly. This is the glue that binds the framework to the Flutter engine. /// +/// When using the rendering framework directly, this binding, or one that +/// implements the same interfaces, must be used. The following +/// mixins are used to implement this binding: +/// +/// * [GestureBinding], which implements the basics of hit testing. +/// * [SchedulerBinding], which introduces the concepts of frames. +/// * [ServicesBinding], which provides access to the plugin subsystem. +/// * [SemanticsBinding], which supports accessibility. +/// * [PaintingBinding], which enables decoding images. +/// * [RendererBinding], which handles the render tree. +/// /// You would only use this binding if you are writing to the /// rendering layer directly. If you are writing to a higher-level /// library, such as the Flutter Widgets library, then you would use -/// that layer's binding. +/// that layer's binding (see [WidgetsFlutterBinding]). class RenderingFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, SemanticsBinding, PaintingBinding, RendererBinding { /// Creates a binding for the rendering layer. /// @@ -545,4 +560,18 @@ class RenderingFlutterBinding extends BindingBase with GestureBinding, Scheduler assert(renderView != null); renderView.child = root; } + + /// Returns an instance of the binding that implements + /// [RendererBinding]. If no binding has yet been initialized, the + /// [RenderingFlutterBinding] class is used to create and initialize + /// one. + /// + /// You need to call this method before using the rendering framework + /// if you are using it directly. If you are using the widgets framework, + /// see [WidgetsFlutterBinding.ensureInitialized]. + static RendererBinding ensureInitialized() { + if (RendererBinding._instance == null) + RenderingFlutterBinding(); + return RendererBinding.instance; + } } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index deb54b94809..7ddc3038c79 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -3498,12 +3498,12 @@ mixin RelayoutWhenSystemFontsChangeMixin on RenderObject { @override void attach(covariant PipelineOwner owner) { super.attach(owner); - PaintingBinding.instance!.systemFonts.addListener(systemFontsDidChange); + PaintingBinding.instance.systemFonts.addListener(systemFontsDidChange); } @override void detach() { - PaintingBinding.instance!.systemFonts.removeListener(systemFontsDidChange); + PaintingBinding.instance.systemFonts.removeListener(systemFontsDidChange); super.detach(); } } diff --git a/packages/flutter/lib/src/rendering/platform_view.dart b/packages/flutter/lib/src/rendering/platform_view.dart index 32df6605312..57d9fc5e809 100644 --- a/packages/flutter/lib/src/rendering/platform_view.dart +++ b/packages/flutter/lib/src/rendering/platform_view.dart @@ -408,12 +408,12 @@ class RenderUiKitView extends RenderBox { @override void attach(PipelineOwner owner) { super.attach(owner); - GestureBinding.instance!.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent); + GestureBinding.instance.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent); } @override void detach() { - GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent); + GestureBinding.instance.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent); _gestureRecognizer!.reset(); super.detach(); } diff --git a/packages/flutter/lib/src/scheduler/binding.dart b/packages/flutter/lib/src/scheduler/binding.dart index 0c104f6417c..056afca436d 100644 --- a/packages/flutter/lib/src/scheduler/binding.dart +++ b/packages/flutter/lib/src/scheduler/binding.dart @@ -18,16 +18,18 @@ export 'dart:ui' show AppLifecycleState, VoidCallback, FrameTiming; /// Slows down animations by this factor to help in development. double get timeDilation => _timeDilation; double _timeDilation = 1.0; -/// Setting the time dilation automatically calls [SchedulerBinding.resetEpoch] -/// to ensure that time stamps seen by consumers of the scheduler binding are -/// always increasing. +/// If the [SchedulerBinding] has been initialized, setting the time dilation +/// automatically calls [SchedulerBinding.resetEpoch] to ensure that time stamps +/// seen by consumers of the scheduler binding are always increasing. +/// +/// It is safe to set this before initializing the binding. set timeDilation(double value) { assert(value > 0.0); if (_timeDilation == value) return; - // We need to resetEpoch first so that we capture start of the epoch with the - // current time dilation. - SchedulerBinding.instance?.resetEpoch(); + // If the binding has been created, we need to resetEpoch first so that we + // capture start of the epoch with the current time dilation. + SchedulerBinding._instance?.resetEpoch(); _timeDilation = value; } @@ -208,6 +210,14 @@ mixin SchedulerBinding on BindingBase { } } + /// The current [SchedulerBinding], if one has been created. + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static SchedulerBinding get instance => BindingBase.checkInstance(_instance); + static SchedulerBinding? _instance; + final List _timingsCallbacks = []; /// Add a [TimingsCallback] that receives [FrameTiming] sent from @@ -307,10 +317,6 @@ mixin SchedulerBinding on BindingBase { } } - /// The current [SchedulerBinding], if one has been created. - static SchedulerBinding? get instance => _instance; - static SchedulerBinding? _instance; - @override void initServiceExtensions() { super.initServiceExtensions(); diff --git a/packages/flutter/lib/src/scheduler/ticker.dart b/packages/flutter/lib/src/scheduler/ticker.dart index 087be6f52a0..18aa6f0f1c2 100644 --- a/packages/flutter/lib/src/scheduler/ticker.dart +++ b/packages/flutter/lib/src/scheduler/ticker.dart @@ -113,9 +113,9 @@ class Ticker { return false; if (muted) return false; - if (SchedulerBinding.instance!.framesEnabled) + if (SchedulerBinding.instance.framesEnabled) return true; - if (SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.idle) + if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.idle) return true; // for example, we might be in a warm-up frame or forced frame return false; } @@ -161,9 +161,9 @@ class Ticker { if (shouldScheduleTick) { scheduleTick(); } - if (SchedulerBinding.instance!.schedulerPhase.index > SchedulerPhase.idle.index && - SchedulerBinding.instance!.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index) - _startTime = SchedulerBinding.instance!.currentFrameTimeStamp; + if (SchedulerBinding.instance.schedulerPhase.index > SchedulerPhase.idle.index && + SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index) + _startTime = SchedulerBinding.instance.currentFrameTimeStamp; return _future!; } @@ -250,7 +250,7 @@ class Ticker { void scheduleTick({ bool rescheduling = false }) { assert(!scheduled); assert(shouldScheduleTick); - _animationId = SchedulerBinding.instance!.scheduleFrameCallback(_tick, rescheduling: rescheduling); + _animationId = SchedulerBinding.instance.scheduleFrameCallback(_tick, rescheduling: rescheduling); } /// Cancels the frame callback that was requested by [scheduleTick], if any. @@ -262,7 +262,7 @@ class Ticker { @protected void unscheduleTick() { if (scheduled) { - SchedulerBinding.instance!.cancelFrameCallbackWithId(_animationId!); + SchedulerBinding.instance.cancelFrameCallbackWithId(_animationId!); _animationId = null; } assert(!shouldScheduleTick); diff --git a/packages/flutter/lib/src/semantics/binding.dart b/packages/flutter/lib/src/semantics/binding.dart index 131ff786d03..34492cdc6bc 100644 --- a/packages/flutter/lib/src/semantics/binding.dart +++ b/packages/flutter/lib/src/semantics/binding.dart @@ -13,10 +13,6 @@ export 'dart:ui' show AccessibilityFeatures; /// The glue between the semantics layer and the Flutter engine. // TODO(jonahwilliams): move the remaining semantic related bindings here. mixin SemanticsBinding on BindingBase { - /// The current [SemanticsBinding], if one has been created. - static SemanticsBinding? get instance => _instance; - static SemanticsBinding? _instance; - @override void initInstances() { super.initInstances(); @@ -24,6 +20,14 @@ mixin SemanticsBinding on BindingBase { _accessibilityFeatures = window.accessibilityFeatures; } + /// The current [SemanticsBinding], if one has been created. + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static SemanticsBinding get instance => BindingBase.checkInstance(_instance); + static SemanticsBinding? _instance; + /// Called when the platform accessibility features change. /// /// See [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged]. diff --git a/packages/flutter/lib/src/semantics/semantics.dart b/packages/flutter/lib/src/semantics/semantics.dart index bd391ce549a..50d89c8420a 100644 --- a/packages/flutter/lib/src/semantics/semantics.dart +++ b/packages/flutter/lib/src/semantics/semantics.dart @@ -2938,7 +2938,7 @@ class SemanticsOwner extends ChangeNotifier { } } visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth); - final ui.SemanticsUpdateBuilder builder = SemanticsBinding.instance!.createSemanticsUpdateBuilder(); + final ui.SemanticsUpdateBuilder builder = SemanticsBinding.instance.createSemanticsUpdateBuilder(); for (final SemanticsNode node in visitedNodes) { assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty) // The _serialize() method marks the node as not dirty, and @@ -2959,7 +2959,7 @@ class SemanticsOwner extends ChangeNotifier { final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!; builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1); } - SemanticsBinding.instance!.window.updateSemantics(builder.build()); + SemanticsBinding.instance.window.updateSemantics(builder.build()); notifyListeners(); } diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index 53659adf577..637eef5ab8c 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -219,7 +219,7 @@ class PlatformAssetBundle extends CachingAssetBundle { Future load(String key) async { final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path); final ByteData? asset = - await ServicesBinding.instance!.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData()); + await ServicesBinding.instance.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData()); if (asset == null) throw FlutterError('Unable to load asset: $key'); return asset; diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart index b5d2c39199b..70894e15189 100644 --- a/packages/flutter/lib/src/services/binding.dart +++ b/packages/flutter/lib/src/services/binding.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -39,7 +38,11 @@ mixin ServicesBinding on BindingBase, SchedulerBinding { } /// The current [ServicesBinding], if one has been created. - static ServicesBinding? get instance => _instance; + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static ServicesBinding get instance => BindingBase.checkInstance(_instance); static ServicesBinding? _instance; /// The default instance of [BinaryMessenger]. diff --git a/packages/flutter/lib/src/services/platform_channel.dart b/packages/flutter/lib/src/services/platform_channel.dart index d0e9db34690..99801381de1 100644 --- a/packages/flutter/lib/src/services/platform_channel.dart +++ b/packages/flutter/lib/src/services/platform_channel.dart @@ -45,7 +45,7 @@ class BasicMessageChannel { final MessageCodec codec; /// The messenger which sends the bytes for this channel, not null. - BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger; + BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger; final BinaryMessenger? _binaryMessenger; /// Sends the specified [message] to the platform plugins on this channel. @@ -118,7 +118,7 @@ class MethodChannel { /// The messenger used by this channel to send platform messages. /// /// The messenger may not be null. - BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger; + BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger; final BinaryMessenger? _binaryMessenger; /// Backend implementation of [invokeMethod]. @@ -450,7 +450,7 @@ class EventChannel { final MethodCodec codec; /// The messenger used by this channel to send platform messages, not null. - BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger; + BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger; final BinaryMessenger? _binaryMessenger; /// Sets up a broadcast stream for receiving events on this channel. diff --git a/packages/flutter/lib/src/services/restoration.dart b/packages/flutter/lib/src/services/restoration.dart index c8d4d882591..1319b994a0c 100644 --- a/packages/flutter/lib/src/services/restoration.dart +++ b/packages/flutter/lib/src/services/restoration.dart @@ -264,7 +264,7 @@ class RestorationManager extends ChangeNotifier { _isReplacing = _rootBucketIsValid && enabled; if (_isReplacing) { - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _isReplacing = false; }); } @@ -350,7 +350,7 @@ class RestorationManager extends ChangeNotifier { _bucketsNeedingSerialization.add(bucket); if (!_serializationScheduled) { _serializationScheduled = true; - SchedulerBinding.instance!.addPostFrameCallback((Duration _) => _doSerialization()); + SchedulerBinding.instance.addPostFrameCallback((Duration _) => _doSerialization()); } } @@ -413,7 +413,7 @@ class RestorationManager extends ChangeNotifier { /// current restoration data is directly sent to the engine. void flushData() { assert(!_debugDoingUpdate); - if (SchedulerBinding.instance!.hasScheduledFrame) { + if (SchedulerBinding.instance.hasScheduledFrame) { return; } _doSerialization(); diff --git a/packages/flutter/lib/src/services/system_chrome.dart b/packages/flutter/lib/src/services/system_chrome.dart index b81d079d1d0..bc0cd733d69 100644 --- a/packages/flutter/lib/src/services/system_chrome.dart +++ b/packages/flutter/lib/src/services/system_chrome.dart @@ -502,7 +502,7 @@ class SystemChrome { /// [SystemUiMode.leanBack]. /// static Future setSystemUIChangeCallback(SystemUiChangeCallback? callback) async { - ServicesBinding.instance!.setSystemUiChangeCallback(callback); + ServicesBinding.instance.setSystemUiChangeCallback(callback); // Skip setting up the listener if there is no callback. if (callback != null) { await SystemChannels.platform.invokeMethod( diff --git a/packages/flutter/lib/src/widgets/actions.dart b/packages/flutter/lib/src/widgets/actions.dart index 616c2f9a027..de24864095c 100644 --- a/packages/flutter/lib/src/widgets/actions.dart +++ b/packages/flutter/lib/src/widgets/actions.dart @@ -1324,7 +1324,7 @@ class _FocusableActionDetectorState extends State { @override void initState() { super.initState(); - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { _updateHighlightMode(FocusManager.instance.highlightMode); }); FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange); @@ -1413,7 +1413,7 @@ class _FocusableActionDetectorState extends State { return _focused && _canShowHighlight && canRequestFocus(target); } - assert(SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.persistentCallbacks); + assert(SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks); final FocusableActionDetector oldTarget = oldWidget ?? widget; final bool didShowHoverHighlight = shouldShowHoverHighlight(oldTarget); final bool didShowFocusHighlight = shouldShowFocusHighlight(oldTarget); @@ -1434,7 +1434,7 @@ class _FocusableActionDetectorState extends State { void didUpdateWidget(FocusableActionDetector oldWidget) { super.didUpdateWidget(oldWidget); if (widget.enabled != oldWidget.enabled) { - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { _mayTriggerCallback(oldWidget: oldWidget); }); } diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart index de53a989ddb..542d8773bda 100644 --- a/packages/flutter/lib/src/widgets/app.dart +++ b/packages/flutter/lib/src/widgets/app.dart @@ -1257,16 +1257,16 @@ class _WidgetsAppState extends State with WidgetsBindingObserver { // If window.defaultRouteName isn't '/', we should assume it was set // intentionally via `setInitialRoute`, and should override whatever is in // [widget.initialRoute]. - String get _initialRouteName => WidgetsBinding.instance!.window.defaultRouteName != Navigator.defaultRouteName - ? WidgetsBinding.instance!.window.defaultRouteName - : widget.initialRoute ?? WidgetsBinding.instance!.window.defaultRouteName; + String get _initialRouteName => WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName + ? WidgetsBinding.instance.window.defaultRouteName + : widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName; @override void initState() { super.initState(); _updateRouting(); - _locale = _resolveLocales(WidgetsBinding.instance!.window.locales, widget.supportedLocales); - WidgetsBinding.instance!.addObserver(this); + _locale = _resolveLocales(WidgetsBinding.instance.window.locales, widget.supportedLocales); + WidgetsBinding.instance.addObserver(this); } @override @@ -1277,7 +1277,7 @@ class _WidgetsAppState extends State with WidgetsBindingObserver { @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _defaultRouteInformationProvider?.dispose(); super.dispose(); } @@ -1681,7 +1681,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg @override void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); } // ACCESSIBILITY @@ -1725,7 +1725,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg @override Widget build(BuildContext context) { - MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window); + MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window); if (!kReleaseMode) { data = data.copyWith(platformBrightness: debugBrightnessOverride); } @@ -1737,7 +1737,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } } diff --git a/packages/flutter/lib/src/widgets/autocomplete.dart b/packages/flutter/lib/src/widgets/autocomplete.dart index 9684fcdb284..be1c6eb8809 100644 --- a/packages/flutter/lib/src/widgets/autocomplete.dart +++ b/packages/flutter/lib/src/widgets/autocomplete.dart @@ -893,7 +893,7 @@ class _RawAutocompleteState extends State> AutocompletePreviousOptionIntent: _previousOptionAction, AutocompleteNextOptionIntent: _nextOptionAction, }; - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _updateOverlay(); }); } @@ -906,7 +906,7 @@ class _RawAutocompleteState extends State> widget.textEditingController, ); _updateFocusNode(oldWidget.focusNode, widget.focusNode); - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _updateOverlay(); }); } diff --git a/packages/flutter/lib/src/widgets/automatic_keep_alive.dart b/packages/flutter/lib/src/widgets/automatic_keep_alive.dart index 1800f03e8f0..19c7b84730e 100644 --- a/packages/flutter/lib/src/widgets/automatic_keep_alive.dart +++ b/packages/flutter/lib/src/widgets/automatic_keep_alive.dart @@ -89,7 +89,7 @@ class _AutomaticKeepAliveState extends State { // If the child doesn't exist yet, we got called during the very first // build of this subtree. Wait until the end of the frame to update // the child when the child is guaranteed to be present. - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { if (!mounted) { return; } @@ -155,7 +155,7 @@ class _AutomaticKeepAliveState extends State { }()); _handles!.remove(handle); if (_handles!.isEmpty) { - if (SchedulerBinding.instance!.schedulerPhase.index < SchedulerPhase.persistentCallbacks.index) { + if (SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.persistentCallbacks.index) { // Build/layout haven't started yet so let's just schedule this for // the next frame. setState(() { _keepingAlive = false; }); diff --git a/packages/flutter/lib/src/widgets/banner.dart b/packages/flutter/lib/src/widgets/banner.dart index 964719a4fc2..67c753bc7ac 100644 --- a/packages/flutter/lib/src/widgets/banner.dart +++ b/packages/flutter/lib/src/widgets/banner.dart @@ -69,7 +69,7 @@ class BannerPainter extends CustomPainter { assert(location != null), assert(color != null), assert(textStyle != null), - super(repaint: PaintingBinding.instance!.systemFonts); + super(repaint: PaintingBinding.instance.systemFonts); /// The message to show in the banner. final String message; diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index 162c548b5ab..e5baec6ee5f 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -50,12 +50,12 @@ export 'dart:ui' show AppLifecycleState, Locale; /// @override /// void initState() { /// super.initState(); -/// WidgetsBinding.instance!.addObserver(this); +/// WidgetsBinding.instance.addObserver(this); /// } /// /// @override /// void dispose() { -/// WidgetsBinding.instance!.removeObserver(this); +/// WidgetsBinding.instance.removeObserver(this); /// super.dispose(); /// } /// @@ -147,19 +147,19 @@ abstract class WidgetsBindingObserver { /// @override /// void initState() { /// super.initState(); - /// _lastSize = WidgetsBinding.instance!.window.physicalSize; - /// WidgetsBinding.instance!.addObserver(this); + /// _lastSize = WidgetsBinding.instance.window.physicalSize; + /// WidgetsBinding.instance.addObserver(this); /// } /// /// @override /// void dispose() { - /// WidgetsBinding.instance!.removeObserver(this); + /// WidgetsBinding.instance.removeObserver(this); /// super.dispose(); /// } /// /// @override /// void didChangeMetrics() { - /// setState(() { _lastSize = WidgetsBinding.instance!.window.physicalSize; }); + /// setState(() { _lastSize = WidgetsBinding.instance.window.physicalSize; }); /// } /// /// @override @@ -203,12 +203,12 @@ abstract class WidgetsBindingObserver { /// @override /// void initState() { /// super.initState(); - /// WidgetsBinding.instance!.addObserver(this); + /// WidgetsBinding.instance.addObserver(this); /// } /// /// @override /// void dispose() { - /// WidgetsBinding.instance!.removeObserver(this); + /// WidgetsBinding.instance.removeObserver(this); /// super.dispose(); /// } /// @@ -216,7 +216,7 @@ abstract class WidgetsBindingObserver { /// /// @override /// void didChangeTextScaleFactor() { - /// setState(() { _lastTextScaleFactor = WidgetsBinding.instance!.window.textScaleFactor; }); + /// setState(() { _lastTextScaleFactor = WidgetsBinding.instance.window.textScaleFactor; }); /// } /// /// @override @@ -296,6 +296,14 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB }()); } + /// The current [WidgetsBinding], if one has been created. + /// + /// Provides access to the features exposed by this mixin. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [runApp] or [WidgetsFlutterBinding.ensureInitialized]. + static WidgetsBinding get instance => BindingBase.checkInstance(_instance); + static WidgetsBinding? _instance; + void _debugAddStackFilters() { const PartialStackFrame elementInflateWidget = PartialStackFrame(package: 'package:flutter/src/widgets/framework.dart', className: 'Element', method: 'inflateWidget'); const PartialStackFrame elementUpdateChild = PartialStackFrame(package: 'package:flutter/src/widgets/framework.dart', className: 'Element', method: 'updateChild'); @@ -377,14 +385,6 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB )); } - /// The current [WidgetsBinding], if one has been created. - /// - /// If you need the binding to be constructed before calling [runApp], - /// you can ensure a Widget binding has been constructed by calling the - /// `WidgetsFlutterBinding.ensureInitialized()` function. - static WidgetsBinding? get instance => _instance; - static WidgetsBinding? _instance; - @override void initServiceExtensions() { super.initServiceExtensions(); @@ -862,14 +862,14 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB developer.Timeline.instantSync('Rasterized first useful frame'); developer.postEvent('Flutter.FirstFrame', {}); } - SchedulerBinding.instance!.removeTimingsCallback(firstFrameCallback!); + SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!); firstFrameCallback = null; _firstFrameCompleter.complete(); }; // Callback is only invoked when FlutterView.render is called. When // sendFramesToEngine is set to false during the frame, it will not be // called and we need to remove the callback (see below). - SchedulerBinding.instance!.addTimingsCallback(firstFrameCallback!); + SchedulerBinding.instance.addTimingsCallback(firstFrameCallback!); } try { @@ -893,7 +893,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB // This frame is deferred and not the first frame sent to the engine that // should be reported. _needToReportFirstFrame = true; - SchedulerBinding.instance!.removeTimingsCallback(firstFrameCallback!); + SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!); } } @@ -938,7 +938,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB child: rootWidget, ).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement?); if (isBootstrapFrame) { - SchedulerBinding.instance!.ensureVisualUpdate(); + SchedulerBinding.instance.ensureVisualUpdate(); } } @@ -1033,12 +1033,11 @@ void runApp(Widget app) { } String _debugDumpAppString() { - assert(WidgetsBinding.instance != null); - const String mode = kDebugMode ? 'DEBUG MODE' : 'PROFILE MODE'; + const String mode = kDebugMode ? 'DEBUG MODE' : kReleaseMode ? 'RELEASE MODE' : 'PROFILE MODE'; final StringBuffer buffer = StringBuffer(); buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode'); - if (WidgetsBinding.instance!.renderViewElement != null) { - buffer.writeln(WidgetsBinding.instance!.renderViewElement!.toStringDeep()); + if (WidgetsBinding.instance.renderViewElement != null) { + buffer.writeln(WidgetsBinding.instance.renderViewElement!.toStringDeep()); } else { buffer.writeln(''); } @@ -1047,8 +1046,7 @@ String _debugDumpAppString() { /// Print a string representation of the currently running app. void debugDumpApp() { - final String value = _debugDumpAppString(); - debugPrint(value); + debugPrint(_debugDumpAppString()); } /// A bridge from a [RenderObject] to an [Element] tree. @@ -1229,22 +1227,34 @@ class RenderObjectToWidgetElement extends RootRenderObje /// A concrete binding for applications based on the Widgets framework. /// /// This is the glue that binds the framework to the Flutter engine. +/// +/// When using the widgets framework, this binding, or one that +/// implements the same interfaces, must be used. The following +/// mixins are used to implement this binding: +/// +/// * [GestureBinding], which implements the basics of hit testing. +/// * [SchedulerBinding], which introduces the concepts of frames. +/// * [ServicesBinding], which provides access to the plugin subsystem. +/// * [PaintingBinding], which enables decoding images. +/// * [SemanticsBinding], which supports accessibility. +/// * [RendererBinding], which handles the render tree. +/// * [WidgetsBinding], which handles the widget tree. class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding { - - /// Returns an instance of the [WidgetsBinding], creating and - /// initializing it if necessary. If one is created, it will be a - /// [WidgetsFlutterBinding]. If one was previously initialized, then - /// it will at least implement [WidgetsBinding]. + /// Returns an instance of the binding that implements + /// [WidgetsBinding]. If no binding has yet been initialized, the + /// [WidgetsFlutterBinding] class is used to create and initialize + /// one. /// /// You only need to call this method if you need the binding to be /// initialized before calling [runApp]. /// /// In the `flutter_test` framework, [testWidgets] initializes the /// binding instance to a [TestWidgetsFlutterBinding], not a - /// [WidgetsFlutterBinding]. + /// [WidgetsFlutterBinding]. See + /// [TestWidgetsFlutterBinding.ensureInitialized]. static WidgetsBinding ensureInitialized() { - if (WidgetsBinding.instance == null) + if (WidgetsBinding._instance == null) WidgetsFlutterBinding(); - return WidgetsBinding.instance!; + return WidgetsBinding.instance; } } diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 2f833a85dca..f164e0b0c02 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -919,7 +919,7 @@ class _DragAvatar extends Drag { _lastOffset = globalPosition - dragStartPoint; _entry!.markNeedsBuild(); final HitTestResult result = HitTestResult(); - WidgetsBinding.instance!.hitTest(result, globalPosition + feedbackOffset); + WidgetsBinding.instance.hitTest(result, globalPosition + feedbackOffset); final List<_DragTargetState> targets = _getDragTargets(result.path).toList(); diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 6ca5f821f72..c336ed5ab71 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -1625,7 +1625,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien if (!_didAutoFocus && widget.autofocus) { _didAutoFocus = true; - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { if (mounted) { FocusScope.of(context).autofocus(widget.focusNode); } @@ -1700,7 +1700,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien _selectionOverlay = null; _focusAttachment!.detach(); widget.focusNode.removeListener(_handleFocusChanged); - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _clipboardStatus?.removeListener(_onChangedClipboardStatus); _clipboardStatus?.dispose(); super.dispose(); @@ -2219,7 +2219,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien return; } _showCaretOnScreenScheduled = true; - SchedulerBinding.instance!.addPostFrameCallback((Duration _) { + SchedulerBinding.instance.addPostFrameCallback((Duration _) { _showCaretOnScreenScheduled = false; if (_currentCaretRect == null || !_scrollController!.hasClients) { return; @@ -2272,10 +2272,10 @@ class EditableTextState extends State with AutomaticKeepAliveClien @override void didChangeMetrics() { - if (_lastBottomViewInset < WidgetsBinding.instance!.window.viewInsets.bottom) { + if (_lastBottomViewInset < WidgetsBinding.instance.window.viewInsets.bottom) { _scheduleShowCaretOnScreen(); } - _lastBottomViewInset = WidgetsBinding.instance!.window.viewInsets.bottom; + _lastBottomViewInset = WidgetsBinding.instance.window.viewInsets.bottom; } @pragma('vm:notify-debugger-on-exception') @@ -2432,8 +2432,8 @@ class EditableTextState extends State with AutomaticKeepAliveClien _updateOrDisposeSelectionOverlayIfNeeded(); if (_hasFocus) { // Listen for changing viewInsets, which indicates keyboard showing up. - WidgetsBinding.instance!.addObserver(this); - _lastBottomViewInset = WidgetsBinding.instance!.window.viewInsets.bottom; + WidgetsBinding.instance.addObserver(this); + _lastBottomViewInset = WidgetsBinding.instance.window.viewInsets.bottom; if (!widget.readOnly) { _scheduleShowCaretOnScreen(); } @@ -2442,7 +2442,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien _handleSelectionChanged(TextSelection.collapsed(offset: _value.text.length), null); } } else { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); // Clear the selection and composition state if this widget lost focus. _value = TextEditingValue(text: _value.text); _currentPromptRectRange = null; @@ -2455,8 +2455,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien final Size size = renderEditable.size; final Matrix4 transform = renderEditable.getTransformTo(null); _textInputConnection!.setEditableSizeAndTransform(size, transform); - SchedulerBinding.instance! - .addPostFrameCallback((Duration _) => _updateSizeAndTransform()); + SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateSizeAndTransform()); } } @@ -2478,8 +2477,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien } assert(composingRect != null); _textInputConnection!.setComposingRect(composingRect); - SchedulerBinding.instance! - .addPostFrameCallback((Duration _) => _updateComposingRectIfNeeded()); + SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateComposingRectIfNeeded()); } } @@ -2491,8 +2489,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien final Rect caretRect = renderEditable.getLocalRectForCaret(currentTextPosition); _textInputConnection!.setCaretRect(caretRect); } - SchedulerBinding.instance! - .addPostFrameCallback((Duration _) => _updateCaretRectIfNeeded()); + SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateCaretRectIfNeeded()); } } diff --git a/packages/flutter/lib/src/widgets/focus_manager.dart b/packages/flutter/lib/src/widgets/focus_manager.dart index 6c442f73a8e..3d6f2a9f55f 100644 --- a/packages/flutter/lib/src/widgets/focus_manager.dart +++ b/packages/flutter/lib/src/widgets/focus_manager.dart @@ -1465,21 +1465,21 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier { void registerGlobalHandlers() { assert(RawKeyboard.instance.keyEventHandler == null); RawKeyboard.instance.keyEventHandler = _handleRawKeyEvent; - GestureBinding.instance!.pointerRouter.addGlobalRoute(_handlePointerEvent); + GestureBinding.instance.pointerRouter.addGlobalRoute(_handlePointerEvent); } @override void dispose() { if (RawKeyboard.instance.keyEventHandler == _handleRawKeyEvent) { RawKeyboard.instance.keyEventHandler = null; - GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handlePointerEvent); + GestureBinding.instance.pointerRouter.removeGlobalRoute(_handlePointerEvent); } super.dispose(); } /// Provides convenient access to the current [FocusManager] singleton from /// the [WidgetsBinding] instance. - static FocusManager get instance => WidgetsBinding.instance!.focusManager; + static FocusManager get instance => WidgetsBinding.instance.focusManager; /// Sets the strategy by which [highlightMode] is determined. /// @@ -1522,7 +1522,7 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier { case TargetPlatform.android: case TargetPlatform.fuchsia: case TargetPlatform.iOS: - if (WidgetsBinding.instance!.mouseTracker.mouseIsConnected) { + if (WidgetsBinding.instance.mouseTracker.mouseIsConnected) { return FocusHighlightMode.traditional; } return FocusHighlightMode.touch; @@ -1821,7 +1821,7 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier { /// Provides convenient access to the current [FocusManager.primaryFocus] from the /// [WidgetsBinding] instance. -FocusNode? get primaryFocus => WidgetsBinding.instance!.focusManager.primaryFocus; +FocusNode? get primaryFocus => WidgetsBinding.instance.focusManager.primaryFocus; /// Returns a text representation of the current focus tree, along with the /// current attributes on each node. diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 8d97a2ee521..c0be36cc3f0 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -149,7 +149,7 @@ abstract class GlobalKey> extends Key { /// constructor. const GlobalKey.constructor() : super.empty(); - Element? get _currentElement => WidgetsBinding.instance!.buildOwner!._globalKeyRegistry[this]; + Element? get _currentElement => WidgetsBinding.instance.buildOwner!._globalKeyRegistry[this]; /// The build context in which the widget with this key builds. /// diff --git a/packages/flutter/lib/src/widgets/heroes.dart b/packages/flutter/lib/src/widgets/heroes.dart index 0f822229074..ab5bac7279a 100644 --- a/packages/flutter/lib/src/widgets/heroes.dart +++ b/packages/flutter/lib/src/widgets/heroes.dart @@ -930,7 +930,7 @@ class HeroController extends NavigatorObserver { // going to end up, and the `to` route will go back onstage. to.offstage = to.animation!.value == 0.0; - WidgetsBinding.instance!.addPostFrameCallback((Duration value) { + WidgetsBinding.instance.addPostFrameCallback((Duration value) { _startHeroTransition(from, to, animation, flightType, isUserGestureTransition); }); } diff --git a/packages/flutter/lib/src/widgets/image.dart b/packages/flutter/lib/src/widgets/image.dart index f397d7fb942..cf2cdd3a56e 100644 --- a/packages/flutter/lib/src/widgets/image.dart +++ b/packages/flutter/lib/src/widgets/image.dart @@ -119,7 +119,7 @@ Future precacheImage( // Give callers until at least the end of the frame to subscribe to the // image stream. // See ImageCache._liveImages - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { stream.removeListener(listener!); }); }, @@ -1118,14 +1118,14 @@ class _ImageState extends State with WidgetsBindingObserver { @override void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); _scrollAwareContext = DisposableBuildContext>(this); } @override void dispose() { assert(_imageStream != null); - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _stopListeningToStream(); _completerHandle?.dispose(); _scrollAwareContext.dispose(); @@ -1175,7 +1175,7 @@ class _ImageState extends State with WidgetsBindingObserver { void _updateInvertColors() { _invertColors = MediaQuery.maybeOf(context)?.invertColors - ?? SemanticsBinding.instance!.accessibilityFeatures.invertColors; + ?? SemanticsBinding.instance.accessibilityFeatures.invertColors; } void _resolveImage() { diff --git a/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart b/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart index 31eead2164e..a7679a3304a 100644 --- a/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart @@ -759,7 +759,7 @@ class _ListWheelScrollViewState extends State { super.didUpdateWidget(oldWidget); if (widget.controller != null && widget.controller != scrollController) { final ScrollController? oldScrollController = scrollController; - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { oldScrollController!.dispose(); }); scrollController = widget.controller; diff --git a/packages/flutter/lib/src/widgets/localizations.dart b/packages/flutter/lib/src/widgets/localizations.dart index d8a771921fa..8a5ab802e40 100644 --- a/packages/flutter/lib/src/widgets/localizations.dart +++ b/packages/flutter/lib/src/widgets/localizations.dart @@ -543,7 +543,7 @@ class _LocalizationsState extends State { // have finished loading. Until then the old locale will continue to be used. // - If we're running at app startup time then defer reporting the first // "useful" frame until after the async load has completed. - RendererBinding.instance!.deferFirstFrame(); + RendererBinding.instance.deferFirstFrame(); typeToResourcesFuture.then((Map value) { if (mounted) { setState(() { @@ -551,7 +551,7 @@ class _LocalizationsState extends State { _locale = locale; }); } - RendererBinding.instance!.allowFirstFrame(); + RendererBinding.instance.allowFirstFrame(); }); } } diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index efb2b329ccf..e7446ca0255 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -3513,7 +3513,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res // controller at the end of the build. if (newHeroController.navigator != null) { final NavigatorState previousOwner = newHeroController.navigator!; - ServicesBinding.instance!.addPostFrameCallback((Duration timestamp) { + ServicesBinding.instance.addPostFrameCallback((Duration timestamp) { // We only check if this navigator still owns the hero controller. if (_heroControllerFromScope == newHeroController) { final bool hasHeroControllerOwnerShip = _heroControllerFromScope!._navigator == this; @@ -5319,7 +5319,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res void _cancelActivePointers() { // TODO(abarth): This mechanism is far from perfect. See https://github.com/flutter/flutter/issues/4770 - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) { + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) { // If we're between frames (SchedulerPhase.idle) then absorb any // subsequent pointers from this frame. The absorbing flag will be // reset in the next frame, see build(). @@ -5330,7 +5330,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res // to false on the next frame. }); } - _activePointers.toList().forEach(WidgetsBinding.instance!.cancelPointer); + _activePointers.toList().forEach(WidgetsBinding.instance.cancelPointer); } @override diff --git a/packages/flutter/lib/src/widgets/nested_scroll_view.dart b/packages/flutter/lib/src/widgets/nested_scroll_view.dart index e527fb42979..9069c3ea314 100644 --- a/packages/flutter/lib/src/widgets/nested_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/nested_scroll_view.dart @@ -1332,7 +1332,7 @@ class _NestedScrollController extends ScrollController { // the position change notifications because those happen synchronously // during a frame, at a time where it's too late to call setState. Since the // result is usually animated, the lag incurred is no big deal. - SchedulerBinding.instance!.addPostFrameCallback( + SchedulerBinding.instance.addPostFrameCallback( (Duration timeStamp) { coordinator.updateShadow(); }, diff --git a/packages/flutter/lib/src/widgets/overlay.dart b/packages/flutter/lib/src/widgets/overlay.dart index 3d736fe4d1b..4e9fc7ed875 100644 --- a/packages/flutter/lib/src/widgets/overlay.dart +++ b/packages/flutter/lib/src/widgets/overlay.dart @@ -151,8 +151,8 @@ class OverlayEntry extends ChangeNotifier { return; overlay._entries.remove(this); - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { overlay._markDirty(); }); } else { diff --git a/packages/flutter/lib/src/widgets/reorderable_list.dart b/packages/flutter/lib/src/widgets/reorderable_list.dart index fb7a77fcda1..50ded8f6672 100644 --- a/packages/flutter/lib/src/widgets/reorderable_list.dart +++ b/packages/flutter/lib/src/widgets/reorderable_list.dart @@ -627,7 +627,7 @@ class SliverReorderableListState extends State with Ticke item.dragging = true; item.rebuild(); _dragStartTransitionComplete = false; - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { _dragStartTransitionComplete = true; }); diff --git a/packages/flutter/lib/src/widgets/restoration.dart b/packages/flutter/lib/src/widgets/restoration.dart index 7fc141d5dc8..66ac8f9dd1a 100644 --- a/packages/flutter/lib/src/widgets/restoration.dart +++ b/packages/flutter/lib/src/widgets/restoration.dart @@ -275,18 +275,18 @@ class _RootRestorationScopeState extends State { void _loadRootBucketIfNecessary() { if (_isWaitingForRootBucket && !_isLoadingRootBucket) { _isLoadingRootBucket = true; - RendererBinding.instance!.deferFirstFrame(); - ServicesBinding.instance!.restorationManager.rootBucket.then((RestorationBucket? bucket) { + RendererBinding.instance.deferFirstFrame(); + ServicesBinding.instance.restorationManager.rootBucket.then((RestorationBucket? bucket) { _isLoadingRootBucket = false; if (mounted) { - ServicesBinding.instance!.restorationManager.addListener(_replaceRootBucket); + ServicesBinding.instance.restorationManager.addListener(_replaceRootBucket); setState(() { _rootBucket = bucket; _rootBucketValid = true; _okToRenderBlankContainer = false; }); } - RendererBinding.instance!.allowFirstFrame(); + RendererBinding.instance.allowFirstFrame(); }); } } @@ -294,7 +294,7 @@ class _RootRestorationScopeState extends State { void _replaceRootBucket() { _rootBucketValid = false; _rootBucket = null; - ServicesBinding.instance!.restorationManager.removeListener(_replaceRootBucket); + ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket); _loadRootBucketIfNecessary(); assert(!_isWaitingForRootBucket); // Ensure that load finished synchronously. } @@ -302,7 +302,7 @@ class _RootRestorationScopeState extends State { @override void dispose() { if (_rootBucketValid) { - ServicesBinding.instance!.restorationManager.removeListener(_replaceRootBucket); + ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket); } super.dispose(); } diff --git a/packages/flutter/lib/src/widgets/router.dart b/packages/flutter/lib/src/widgets/router.dart index 8610aa2ce61..d95618be47b 100644 --- a/packages/flutter/lib/src/widgets/router.dart +++ b/packages/flutter/lib/src/widgets/router.dart @@ -504,7 +504,7 @@ class _RouterState extends State> with RestorationMixin { return; assert(_currentIntentionToReport != _IntentionToReportRouteInformation.none); _routeInformationReportingTaskScheduled = true; - SchedulerBinding.instance!.addPostFrameCallback(_reportRouteInformation); + SchedulerBinding.instance.addPostFrameCallback(_reportRouteInformation); } void _reportRouteInformation(Duration timestamp) { @@ -962,7 +962,7 @@ class RootBackButtonDispatcher extends BackButtonDispatcher with WidgetsBindingO @override void addCallback(ValueGetter> callback) { if (!hasCallbacks) - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); super.addCallback(callback); } @@ -970,7 +970,7 @@ class RootBackButtonDispatcher extends BackButtonDispatcher with WidgetsBindingO void removeCallback(ValueGetter> callback) { super.removeCallback(callback); if (!hasCallbacks) - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); } @override @@ -1356,7 +1356,7 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid @override void addListener(VoidCallback listener) { if (!hasListeners) - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); super.addListener(listener); } @@ -1364,7 +1364,7 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid void removeListener(VoidCallback listener) { super.removeListener(listener); if (!hasListeners) - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); } @override @@ -1374,7 +1374,7 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid // is no longer being used, there's no listener, and so it will get garbage // collected. if (hasListeners) - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index e27090c926b..9810dc4a130 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -616,11 +616,11 @@ mixin LocalHistoryRoute on Route { entry._owner = null; entry._notifyRemoved(); if (_localHistory!.isEmpty) { - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) { // The local history might be removed as a result of disposing inactive // elements during finalizeTree. The state is locked at this moment, and // we can only notify state has changed in the next frame. - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { changedInternalState(); }); } else { diff --git a/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart b/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart index 27f784a7353..8e3f4d3eeaa 100644 --- a/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart +++ b/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart @@ -83,7 +83,7 @@ class ScrollAwareImageProvider extends ImageProvider { // Do this before checking scrolling, so that if the bytes are available we // render them even though we're scrolling fast - there's no additional // allocations to do for texture memory, it's already there. - if (stream.completer != null || PaintingBinding.instance!.imageCache!.containsKey(key)) { + if (stream.completer != null || PaintingBinding.instance.imageCache.containsKey(key)) { imageProvider.resolveStreamForKey(configuration, stream, key, handleError); return; } @@ -96,7 +96,7 @@ class ScrollAwareImageProvider extends ImageProvider { // Try to get to end of the frame callbacks of the next frame, and then // check again. if (Scrollable.recommendDeferredLoadingForContext(context.context!)) { - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrameCallback((Duration timeStamp) { scheduleMicrotask(() => resolveStreamForKey(configuration, stream, key, handleError)); }); return; diff --git a/packages/flutter/lib/src/widgets/scroll_physics.dart b/packages/flutter/lib/src/widgets/scroll_physics.dart index 8e3e18809e0..16029f48434 100644 --- a/packages/flutter/lib/src/widgets/scroll_physics.dart +++ b/packages/flutter/lib/src/widgets/scroll_physics.dart @@ -224,7 +224,7 @@ class ScrollPhysics { assert(metrics != null); assert(context != null); if (parent == null) { - final double maxPhysicalPixels = WidgetsBinding.instance!.window.physicalSize.longestSide; + final double maxPhysicalPixels = WidgetsBinding.instance.window.physicalSize.longestSide; return velocity.abs() > maxPhysicalPixels; } return parent!.recommendDeferredLoading(velocity, metrics, context); @@ -356,8 +356,8 @@ class ScrollPhysics { static final Tolerance _kDefaultTolerance = Tolerance( // TODO(ianh): Handle the case of the device pixel ratio changing. // TODO(ianh): Get this from the local MediaQuery not dart:ui's window object. - velocity: 1.0 / (0.050 * WidgetsBinding.instance!.window.devicePixelRatio), // logical pixels per second - distance: 1.0 / WidgetsBinding.instance!.window.devicePixelRatio, // logical pixels + velocity: 1.0 / (0.050 * WidgetsBinding.instance.window.devicePixelRatio), // logical pixels per second + distance: 1.0 / WidgetsBinding.instance.window.devicePixelRatio, // logical pixels ); /// The tolerance to use for ballistic simulations. diff --git a/packages/flutter/lib/src/widgets/scroll_position.dart b/packages/flutter/lib/src/widgets/scroll_position.dart index 08432fd50d9..2706eed29d4 100644 --- a/packages/flutter/lib/src/widgets/scroll_position.dart +++ b/packages/flutter/lib/src/widgets/scroll_position.dart @@ -254,7 +254,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics { /// If there is any overscroll, it is reported using [didOverscrollBy]. double setPixels(double newPixels) { assert(hasPixels); - assert(SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.persistentCallbacks, "A scrollable's position should not change during the build, layout, and paint phases, otherwise the rendering will be confused."); + assert(SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks, "A scrollable's position should not change during the build, layout, and paint phases, otherwise the rendering will be confused."); if (newPixels != pixels) { final double overscroll = applyBoundaryConditions(newPixels); assert(() { @@ -375,7 +375,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics { _impliedVelocity = value - pixels; _pixels = value; notifyListeners(); - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { _impliedVelocity = 0; }); } diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 27792796f92..c2174d705f1 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -440,7 +440,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R _persistedScrollOffset.value = offset; // [saveOffset] is called after a scrolling ends and it is usually not // followed by a frame. Therefore, manually flush restoration data. - ServicesBinding.instance!.restorationManager.flushData(); + ServicesBinding.instance.restorationManager.flushData(); } @override @@ -705,7 +705,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta); // Only express interest in the event if it would actually result in a scroll. if (delta != 0.0 && targetScrollOffset != position.pixels) { - GestureBinding.instance!.pointerSignalResolver.register(event, _handlePointerScroll); + GestureBinding.instance.pointerSignalResolver.register(event, _handlePointerScroll); } } } diff --git a/packages/flutter/lib/src/widgets/scrollbar.dart b/packages/flutter/lib/src/widgets/scrollbar.dart index efa022aefc9..ad9ca97a114 100644 --- a/packages/flutter/lib/src/widgets/scrollbar.dart +++ b/packages/flutter/lib/src/widgets/scrollbar.dart @@ -1172,7 +1172,7 @@ class RawScrollbarState extends State with TickerProv // This allows the thumb to show immediately when isAlwaysShown is true. // A scroll event is required in order to paint the thumb. void _maybeTriggerScrollbar() { - WidgetsBinding.instance!.addPostFrameCallback((Duration duration) { + WidgetsBinding.instance.addPostFrameCallback((Duration duration) { final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context); if (showScrollbar) { _fadeoutTimer?.cancel(); diff --git a/packages/flutter/lib/src/widgets/semantics_debugger.dart b/packages/flutter/lib/src/widgets/semantics_debugger.dart index 8a0817ae89b..3945c4d0069 100644 --- a/packages/flutter/lib/src/widgets/semantics_debugger.dart +++ b/packages/flutter/lib/src/widgets/semantics_debugger.dart @@ -58,9 +58,9 @@ class _SemanticsDebuggerState extends State with WidgetsBindi // static here because we might not be in a tree that's attached to that // binding. Instead, we should find a way to get to the PipelineOwner from // the BuildContext. - _client = _SemanticsClient(WidgetsBinding.instance!.pipelineOwner) + _client = _SemanticsClient(WidgetsBinding.instance.pipelineOwner) ..addListener(_update); - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); } @override @@ -68,7 +68,7 @@ class _SemanticsDebuggerState extends State with WidgetsBindi _client ..removeListener(_update) ..dispose(); - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -80,7 +80,7 @@ class _SemanticsDebuggerState extends State with WidgetsBindi } void _update() { - SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { // Semantic information are only available at the end of a frame and our // only chance to paint them on the screen is the next frame. To achieve // this, we call setState() in a post-frame callback. @@ -98,7 +98,7 @@ class _SemanticsDebuggerState extends State with WidgetsBindi Offset? _lastPointerDownLocation; void _handlePointerDown(PointerDownEvent event) { setState(() { - _lastPointerDownLocation = event.position * WidgetsBinding.instance!.window.devicePixelRatio; + _lastPointerDownLocation = event.position * WidgetsBinding.instance.window.devicePixelRatio; }); // TODO(ianh): Use a gesture recognizer so that we can reset the // _lastPointerDownLocation when none of the other gesture recognizers win. @@ -150,7 +150,7 @@ class _SemanticsDebuggerState extends State with WidgetsBindi // TODO(abarth): This shouldn't be a static. We should get the pipeline owner // from [context] somehow. - PipelineOwner get _pipelineOwner => WidgetsBinding.instance!.pipelineOwner; + PipelineOwner get _pipelineOwner => WidgetsBinding.instance.pipelineOwner; @override Widget build(BuildContext context) { @@ -159,7 +159,7 @@ class _SemanticsDebuggerState extends State with WidgetsBindi _pipelineOwner, _client.generation, _lastPointerDownLocation, // in physical pixels - WidgetsBinding.instance!.window.devicePixelRatio, + WidgetsBinding.instance.window.devicePixelRatio, widget.labelStyle, ), child: GestureDetector( diff --git a/packages/flutter/lib/src/widgets/text_selection.dart b/packages/flutter/lib/src/widgets/text_selection.dart index 04fd4878f17..5b9900d27b9 100644 --- a/packages/flutter/lib/src/widgets/text_selection.dart +++ b/packages/flutter/lib/src/widgets/text_selection.dart @@ -472,8 +472,8 @@ class TextSelectionOverlay { _handlesVisible = visible; // If we are in build state, it will be too late to update visibility. // We will need to schedule the build in next frame. - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance!.addPostFrameCallback(_markNeedsBuild); + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) { + SchedulerBinding.instance.addPostFrameCallback(_markNeedsBuild); } else { _markNeedsBuild(); } @@ -523,8 +523,8 @@ class TextSelectionOverlay { if (_value == newValue) return; _value = newValue; - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance!.addPostFrameCallback(_markNeedsBuild); + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) { + SchedulerBinding.instance.addPostFrameCallback(_markNeedsBuild); } else { _markNeedsBuild(); } @@ -1657,7 +1657,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget @override void addListener(VoidCallback listener) { if (!hasListeners) { - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); } if (value == ClipboardStatus.unknown) { update(); @@ -1669,7 +1669,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget void removeListener(VoidCallback listener) { super.removeListener(listener); if (!hasListeners) { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); } } @@ -1689,7 +1689,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget @override void dispose() { super.dispose(); - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _disposed = true; } } diff --git a/packages/flutter/lib/src/widgets/widget_inspector.dart b/packages/flutter/lib/src/widgets/widget_inspector.dart index eb4e453a9fe..a8375deb2fa 100644 --- a/packages/flutter/lib/src/widgets/widget_inspector.dart +++ b/packages/flutter/lib/src/widgets/widget_inspector.dart @@ -908,7 +908,7 @@ mixin WidgetInspectorService { /// This is expensive and should not be called except during development. @protected Future forceRebuild() { - final WidgetsBinding binding = WidgetsBinding.instance!; + final WidgetsBinding binding = WidgetsBinding.instance; if (binding.renderViewElement != null) { binding.buildOwner!.reassemble(binding.renderViewElement!, null); return binding.endOfFrame; @@ -992,7 +992,7 @@ mixin WidgetInspectorService { return true; }()); - SchedulerBinding.instance!.addPersistentFrameCallback(_onFrameStart); + SchedulerBinding.instance.addPersistentFrameCallback(_onFrameStart); final FlutterExceptionHandler defaultExceptionHandler = FlutterError.presentError; @@ -1061,7 +1061,7 @@ mixin WidgetInspectorService { renderObject.markNeedsPaint(); renderObject.visitChildren(markTreeNeedsPaint); } - final RenderObject root = RendererBinding.instance!.renderView; + final RenderObject root = RendererBinding.instance.renderView; markTreeNeedsPaint(root); } else { debugOnProfilePaint = null; @@ -1284,7 +1284,7 @@ mixin WidgetInspectorService { @protected bool isWidgetTreeReady([ String? groupName ]) { return WidgetsBinding.instance != null && - WidgetsBinding.instance!.debugDidSendFirstFrameEvent; + WidgetsBinding.instance.debugDidSendFirstFrameEvent; } /// Returns the Dart object associated with a reference id. @@ -1388,12 +1388,12 @@ mixin WidgetInspectorService { developer.inspect(selection.current); } if (selectionChangedCallback != null) { - if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) { + if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) { selectionChangedCallback!(); } else { // It isn't safe to trigger the selection change callback if we are in // the middle of rendering the frame. - SchedulerBinding.instance!.scheduleTask( + SchedulerBinding.instance.scheduleTask( selectionChangedCallback!, Priority.touch, ); @@ -1690,7 +1690,7 @@ mixin WidgetInspectorService { } Map? _getRootWidget(String groupName) { - return _nodeToJson(WidgetsBinding.instance?.renderViewElement?.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this)); + return _nodeToJson(WidgetsBinding.instance.renderViewElement?.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this)); } /// Returns a JSON representation of the [DiagnosticsNode] for the root @@ -1701,7 +1701,7 @@ mixin WidgetInspectorService { Map? _getRootWidgetSummaryTree(String groupName) { return _nodeToJson( - WidgetsBinding.instance?.renderViewElement?.toDiagnosticsNode(), + WidgetsBinding.instance.renderViewElement?.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, subtreeDepth: 1000000, summaryTree: true, service: this), ); } @@ -1714,7 +1714,7 @@ mixin WidgetInspectorService { } Map? _getRootRenderObject(String groupName) { - return _nodeToJson(RendererBinding.instance?.renderView.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this)); + return _nodeToJson(RendererBinding.instance.renderView.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this)); } /// Returns a JSON representation of the subtree rooted at the @@ -1907,7 +1907,7 @@ mixin WidgetInspectorService { void _onFrameStart(Duration timeStamp) { _frameStart = timeStamp; - SchedulerBinding.instance!.addPostFrameCallback(_onFrameEnd); + SchedulerBinding.instance.addPostFrameCallback(_onFrameEnd); } void _onFrameEnd(Duration timeStamp) { @@ -2356,7 +2356,7 @@ class _WidgetInspectorState extends State // on the edge of the display. If the pointer is being dragged off the edge // of the display we do not want to select anything. A user can still select // a widget that is only at the exact screen margin by tapping. - final Rect bounds = (Offset.zero & (WidgetsBinding.instance!.window.physicalSize / WidgetsBinding.instance!.window.devicePixelRatio)).deflate(_kOffScreenMargin); + final Rect bounds = (Offset.zero & (WidgetsBinding.instance.window.physicalSize / WidgetsBinding.instance.window.devicePixelRatio)).deflate(_kOffScreenMargin); if (!bounds.contains(_lastPointerLocation!)) { setState(() { selection.clear(); diff --git a/packages/flutter/test/animation/animation_controller_test.dart b/packages/flutter/test/animation/animation_controller_test.dart index 2aff62d3a83..2785b9fe84b 100644 --- a/packages/flutter/test/animation/animation_controller_test.dart +++ b/packages/flutter/test/animation/animation_controller_test.dart @@ -16,7 +16,7 @@ import '../scheduler/scheduler_tester.dart'; void main() { setUp(() { WidgetsFlutterBinding.ensureInitialized(); - WidgetsBinding.instance!.resetEpoch(); + WidgetsBinding.instance.resetEpoch(); ui.window.onBeginFrame = null; ui.window.onDrawFrame = null; }); @@ -502,7 +502,7 @@ void main() { controller.forward(from: 0.2); expect(controller.value, 0.2); controller.animateTo(1.0, duration: Duration.zero); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.'); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0), reason: 'Expected no animation.'); expect(controller.value, 1.0); }); diff --git a/packages/flutter/test/animation/animations_test.dart b/packages/flutter/test/animation/animations_test.dart index 575d4eac019..50d366f71b1 100644 --- a/packages/flutter/test/animation/animations_test.dart +++ b/packages/flutter/test/animation/animations_test.dart @@ -17,7 +17,7 @@ class BogusCurve extends Curve { void main() { setUp(() { WidgetsFlutterBinding.ensureInitialized(); - WidgetsBinding.instance!.resetEpoch(); + WidgetsBinding.instance.resetEpoch(); ui.window.onBeginFrame = null; ui.window.onDrawFrame = null; }); diff --git a/packages/flutter/test/animation/iteration_patterns_test.dart b/packages/flutter/test/animation/iteration_patterns_test.dart index d2452510dba..e1988b8cd16 100644 --- a/packages/flutter/test/animation/iteration_patterns_test.dart +++ b/packages/flutter/test/animation/iteration_patterns_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { setUp(() { WidgetsFlutterBinding.ensureInitialized(); - WidgetsBinding.instance!.resetEpoch(); + WidgetsBinding.instance.resetEpoch(); }); test('AnimationController with mutating listener', () { diff --git a/packages/flutter/test/cupertino/activity_indicator_test.dart b/packages/flutter/test/cupertino/activity_indicator_test.dart index d25ae0c2d9e..c726486e3e3 100644 --- a/packages/flutter/test/cupertino/activity_indicator_test.dart +++ b/packages/flutter/test/cupertino/activity_indicator_test.dart @@ -11,18 +11,18 @@ import '../rendering/mock_canvas.dart'; void main() { testWidgets('Activity indicator animate property works', (WidgetTester tester) async { await tester.pumpWidget(buildCupertinoActivityIndicator()); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); await tester.pumpWidget(buildCupertinoActivityIndicator(false)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.pumpWidget(Container()); await tester.pumpWidget(buildCupertinoActivityIndicator(false)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.pumpWidget(buildCupertinoActivityIndicator()); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); }); testWidgets('Activity indicator dark mode', (WidgetTester tester) async { diff --git a/packages/flutter/test/cupertino/app_test.dart b/packages/flutter/test/cupertino/app_test.dart index fa987ef137e..0825e6498e1 100644 --- a/packages/flutter/test/cupertino/app_test.dart +++ b/packages/flutter/test/cupertino/app_test.dart @@ -171,7 +171,7 @@ void main() { // Simulate android back button intent. final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); }); diff --git a/packages/flutter/test/cupertino/button_test.dart b/packages/flutter/test/cupertino/button_test.dart index e4b51b41410..f6151ba4ff8 100644 --- a/packages/flutter/test/cupertino/button_test.dart +++ b/packages/flutter/test/cupertino/button_test.dart @@ -176,11 +176,11 @@ void main() { expect(value, isFalse); // No animating by default. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.tap(find.byType(CupertinoButton)); expect(value, isTrue); // Animates. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); }); testWidgets("Disabled button doesn't animate", (WidgetTester tester) async { @@ -188,10 +188,10 @@ void main() { onPressed: null, child: Text('Tap me'), ))); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.tap(find.byType(CupertinoButton)); // Still doesn't animate. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('pressedOpacity defaults to 0.1', (WidgetTester tester) async { diff --git a/packages/flutter/test/cupertino/context_menu_test.dart b/packages/flutter/test/cupertino/context_menu_test.dart index cb7fbf24367..d3b1c8c265c 100644 --- a/packages/flutter/test/cupertino/context_menu_test.dart +++ b/packages/flutter/test/cupertino/context_menu_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { final TestWidgetsFlutterBinding binding = - TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + TestWidgetsFlutterBinding.ensureInitialized(); const double _kOpenScale = 1.1; Widget _getChild() { diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart index ec0373ead68..9f3267e88a4 100644 --- a/packages/flutter/test/cupertino/route_test.dart +++ b/packages/flutter/test/cupertino/route_test.dart @@ -1809,7 +1809,7 @@ Widget buildNavigator({ TransitionDelegate? transitionDelegate, }) { return MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ diff --git a/packages/flutter/test/cupertino/slider_test.dart b/packages/flutter/test/cupertino/slider_test.dart index 89efd9eda0f..6b763fc0e22 100644 --- a/packages/flutter/test/cupertino/slider_test.dart +++ b/packages/flutter/test/cupertino/slider_test.dart @@ -64,7 +64,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider does not move when tapped (RTL)', (WidgetTester tester) async { @@ -100,7 +100,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider calls onChangeStart once when interaction begins', (WidgetTester tester) async { @@ -141,7 +141,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider calls onChangeEnd once after interaction has ended', (WidgetTester tester) async { @@ -182,7 +182,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider moves when dragged (LTR)', (WidgetTester tester) async { @@ -236,7 +236,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider moves when dragged (RTL)', (WidgetTester tester) async { @@ -290,7 +290,7 @@ void main() { await tester.pump(); // No animation should start. // Check the transientCallbackCount before tearing down the widget to ensure // that no animation is running. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider Semantics', (WidgetTester tester) async { diff --git a/packages/flutter/test/gestures/debug_test.dart b/packages/flutter/test/gestures/debug_test.dart index b2b24bc04d4..2d983d8015b 100644 --- a/packages/flutter/test/gestures/debug_test.dart +++ b/packages/flutter/test/gestures/debug_test.dart @@ -28,19 +28,19 @@ void main() { expect(log[1], equalsIgnoringHashCodes('Gesture arena 1 ❙ Adding: TapGestureRecognizer#00000(state: ready, button: 1)')); log.clear(); - GestureBinding.instance!.gestureArena.close(1); + GestureBinding.instance.gestureArena.close(1); expect(log, hasLength(1)); expect(log[0], equalsIgnoringHashCodes('Gesture arena 1 ❙ Closing with 1 member.')); log.clear(); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); event = const PointerUpEvent(pointer: 1, position: Offset(12.0, 8.0)); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(log, hasLength(2)); expect(log[0], equalsIgnoringHashCodes('Gesture arena 1 ❙ Sweeping with 1 member.')); expect(log[1], equalsIgnoringHashCodes('Gesture arena 1 ❙ Winner: TapGestureRecognizer#00000(state: ready, finalPosition: Offset(12.0, 8.0), button: 1)')); @@ -71,17 +71,17 @@ void main() { tap.addPointer(event as PointerDownEvent); expect(log, isEmpty); - GestureBinding.instance!.gestureArena.close(1); + GestureBinding.instance.gestureArena.close(1); expect(log, isEmpty); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); event = const PointerUpEvent(pointer: 1, position: Offset(12.0, 8.0)); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(log, hasLength(3)); expect(log[0], equalsIgnoringHashCodes('TapGestureRecognizer#00000(state: ready, finalPosition: Offset(12.0, 8.0), button: 1) calling onTapDown callback.')); expect(log[1], equalsIgnoringHashCodes('TapGestureRecognizer#00000(state: ready, won arena, finalPosition: Offset(12.0, 8.0), button: 1, sent tap down) calling onTapUp callback.')); @@ -117,19 +117,19 @@ void main() { expect(log[1], equalsIgnoringHashCodes('Gesture arena 1 ❙ Adding: TapGestureRecognizer#00000(state: ready, button: 1)')); log.clear(); - GestureBinding.instance!.gestureArena.close(1); + GestureBinding.instance.gestureArena.close(1); expect(log, hasLength(1)); expect(log[0], equalsIgnoringHashCodes('Gesture arena 1 ❙ Closing with 1 member.')); log.clear(); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); event = const PointerUpEvent(pointer: 1, position: Offset(12.0, 8.0)); - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); expect(log, isEmpty); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(log, hasLength(5)); expect(log[0], equalsIgnoringHashCodes('Gesture arena 1 ❙ Sweeping with 1 member.')); expect(log[1], equalsIgnoringHashCodes('Gesture arena 1 ❙ Winner: TapGestureRecognizer#00000(state: ready, finalPosition: Offset(12.0, 8.0), button: 1)')); diff --git a/packages/flutter/test/gestures/double_tap_test.dart b/packages/flutter/test/gestures/double_tap_test.dart index 4da59cc3b01..38bb092702c 100644 --- a/packages/flutter/test/gestures/double_tap_test.dart +++ b/packages/flutter/test/gestures/double_tap_test.dart @@ -24,13 +24,14 @@ class TestGestureArenaMember extends GestureArenaMember { } void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + late DoubleTapGestureRecognizer tap; bool doubleTapRecognized = false; TapDownDetails? doubleTapDownDetails; bool doubleTapCanceled = false; setUp(() { - ensureGestureBinding(); tap = DoubleTapGestureRecognizer(); doubleTapRecognized = false; @@ -133,7 +134,7 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapDownDetails, isNull); tester.async.elapse(const Duration(milliseconds: 100)); @@ -147,7 +148,7 @@ void main() { tester.route(up2); expect(doubleTapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapCanceled, isFalse); }); @@ -156,13 +157,13 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tap.addPointer(down3); tester.closeArena(3); tester.route(down3); tester.route(up3); - GestureBinding.instance!.gestureArena.sweep(3); + GestureBinding.instance.gestureArena.sweep(3); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -176,13 +177,13 @@ void main() { tester.route(move4); tester.route(up4); - GestureBinding.instance!.gestureArena.sweep(4); + GestureBinding.instance.gestureArena.sweep(4); tap.addPointer(down1); tester.closeArena(1); tester.route(down2); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -194,14 +195,14 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.async.elapse(const Duration(milliseconds: 5000)); tap.addPointer(down2); tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -213,14 +214,14 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.async.elapse(const Duration(milliseconds: 5000)); tap.addPointer(down2); tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapDownDetails, isNull); tester.async.elapse(const Duration(milliseconds: 100)); @@ -234,7 +235,7 @@ void main() { tester.route(up5); expect(doubleTapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(5); + GestureBinding.instance.gestureArena.sweep(5); expect(doubleTapCanceled, isFalse); }); @@ -244,7 +245,7 @@ void main() { tester.route(down1); tester.async.elapse(const Duration(milliseconds: 1000)); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapDownDetails, isNull); tap.addPointer(down2); @@ -257,7 +258,7 @@ void main() { tester.route(up2); expect(doubleTapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapCanceled, isFalse); }); @@ -271,10 +272,10 @@ void main() { tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -291,10 +292,10 @@ void main() { tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapDownDetails, isNull); tester.async.elapse(const Duration(milliseconds: 100)); @@ -308,27 +309,27 @@ void main() { tester.route(up1); expect(doubleTapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapCanceled, isFalse); }); testGesture('Should cancel on arena reject during first tap', (GestureTester tester) { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - final GestureArenaEntry entry = GestureBinding.instance!.gestureArena.add(1, member); + final GestureArenaEntry entry = GestureBinding.instance.gestureArena.add(1, member); tester.closeArena(1); tester.route(down1); tester.route(up1); entry.resolve(GestureDisposition.accepted); expect(member.accepted, isTrue); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tap.addPointer(down2); tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -338,11 +339,11 @@ void main() { testGesture('Should cancel on arena reject between taps', (GestureTester tester) { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - final GestureArenaEntry entry = GestureBinding.instance!.gestureArena.add(1, member); + final GestureArenaEntry entry = GestureBinding.instance.gestureArena.add(1, member); tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); entry.resolve(GestureDisposition.accepted); expect(member.accepted, isTrue); @@ -351,7 +352,7 @@ void main() { tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -361,11 +362,11 @@ void main() { testGesture('Should cancel on arena reject during last tap', (GestureTester tester) { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - final GestureArenaEntry entry = GestureBinding.instance!.gestureArena.add(1, member); + final GestureArenaEntry entry = GestureBinding.instance.gestureArena.add(1, member); tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapDownDetails, isNull); tester.async.elapse(const Duration(milliseconds: 100)); @@ -382,7 +383,7 @@ void main() { expect(doubleTapCanceled, isTrue); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); }); @@ -390,11 +391,11 @@ void main() { FakeAsync().run((FakeAsync async) { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - GestureBinding.instance!.gestureArena.add(1, member); + GestureBinding.instance.gestureArena.add(1, member); tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(member.accepted, isFalse); async.elapse(const Duration(milliseconds: 5000)); @@ -411,14 +412,14 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.async.elapse(const Duration(milliseconds: 10)); tap.addPointer(down2); tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -430,14 +431,14 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.async.elapse(const Duration(milliseconds: 10)); tap.addPointer(down2); tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapDownDetails, isNull); tester.async.elapse(const Duration(milliseconds: 100)); @@ -451,7 +452,7 @@ void main() { tester.route(up5); expect(doubleTapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(5); + GestureBinding.instance.gestureArena.sweep(5); expect(doubleTapCanceled, isFalse); }); @@ -468,7 +469,7 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); tester.async.elapse(interval); @@ -476,7 +477,7 @@ void main() { tester.closeArena(6); tester.route(down6); tester.route(up6); - GestureBinding.instance!.gestureArena.sweep(6); + GestureBinding.instance.gestureArena.sweep(6); tester.async.elapse(interval); expect(doubleTapRecognized, isFalse); @@ -485,7 +486,7 @@ void main() { tester.closeArena(2); tester.route(down2); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -503,7 +504,7 @@ void main() { tester.closeArena(6); tester.route(down6); tester.route(up6); - GestureBinding.instance!.gestureArena.sweep(6); + GestureBinding.instance.gestureArena.sweep(6); tester.async.elapse(interval); @@ -511,7 +512,7 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); expect(doubleTapDownDetails, isNull); @@ -524,7 +525,7 @@ void main() { expect(doubleTapDownDetails!.globalPosition, down2.position); expect(doubleTapDownDetails!.localPosition, down2.localPosition); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(doubleTapRecognized, isTrue); expect(doubleTapCanceled, isFalse); @@ -610,7 +611,7 @@ void main() { tester.closeArena(6); tester.route(down6); tester.route(up6); - GestureBinding.instance!.gestureArena.sweep(6); + GestureBinding.instance.gestureArena.sweep(6); tester.async.elapse(const Duration(milliseconds: 100)); doubleTap.addPointer(down7); @@ -637,7 +638,7 @@ void main() { tester.closeArena(1); tester.route(down1); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); // Open a new arena with only one TapGestureRecognizer. tester.async.elapse(const Duration(milliseconds: 100)); @@ -648,7 +649,7 @@ void main() { tester.route(move2); tester.route(up2); expect(tapCount, 1); // The second tap will win immediately. - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); // Finish the previous gesture arena. tester.async.elapse(const Duration(milliseconds: 300)); diff --git a/packages/flutter/test/gestures/drag_test.dart b/packages/flutter/test/gestures/drag_test.dart index f97e1b495d3..8ad6e3d52dc 100644 --- a/packages/flutter/test/gestures/drag_test.dart +++ b/packages/flutter/test/gestures/drag_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('Should recognize pan', (GestureTester tester) { final PanGestureRecognizer pan = PanGestureRecognizer(); @@ -1135,12 +1135,12 @@ void main() { logs.clear(); tester.route(pointer1.up()); - GestureBinding.instance!.gestureArena.sweep(pointer1.pointer); + GestureBinding.instance.gestureArena.sweep(pointer1.pointer); expect(logs, ['downT', 'upT']); logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); expect(logs, ['cancelH']); logs.clear(); }, @@ -1188,13 +1188,13 @@ void main() { logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); // Tap is not triggered because pointer2 is not its primary pointer expect(logs, []); logs.clear(); tester.route(pointer1.up()); - GestureBinding.instance!.gestureArena.sweep(pointer1.pointer); + GestureBinding.instance.gestureArena.sweep(pointer1.pointer); expect(logs, ['cancelH', 'downT', 'upT']); logs.clear(); }, @@ -1246,12 +1246,12 @@ void main() { logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); expect(logs, []); logs.clear(); tester.route(pointer1.up()); - GestureBinding.instance!.gestureArena.sweep(pointer1.pointer); + GestureBinding.instance.gestureArena.sweep(pointer1.pointer); expect(logs, ['endH']); logs.clear(); }, @@ -1299,7 +1299,7 @@ void main() { logs.clear(); tester.route(pointer1.up()); - GestureBinding.instance!.gestureArena.sweep(pointer1.pointer); + GestureBinding.instance.gestureArena.sweep(pointer1.pointer); expect(logs, ['downT', 'upT']); logs.clear(); @@ -1308,7 +1308,7 @@ void main() { logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); expect(logs, ['endH']); logs.clear(); }, @@ -1364,7 +1364,7 @@ void main() { logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); expect(logs, ['endH']); logs.clear(); }, @@ -1426,7 +1426,7 @@ void main() { logs.clear(); tester.route(pointer2.up()); - GestureBinding.instance!.gestureArena.sweep(pointer2.pointer); + GestureBinding.instance.gestureArena.sweep(pointer2.pointer); expect(logs, []); tester.route(pointer4.cancel()); diff --git a/packages/flutter/test/gestures/events_test.dart b/packages/flutter/test/gestures/events_test.dart index 6e27efefaba..ddaf43c321f 100644 --- a/packages/flutter/test/gestures/events_test.dart +++ b/packages/flutter/test/gestures/events_test.dart @@ -10,7 +10,7 @@ import 'package:vector_math/vector_math_64.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('toString control tests', (GestureTester tester) { expect(const PointerDownEvent(), hasOneLineDescription); diff --git a/packages/flutter/test/gestures/force_press_test.dart b/packages/flutter/test/gestures/force_press_test.dart index d3f5a19c46a..90d36ba19ee 100644 --- a/packages/flutter/test/gestures/force_press_test.dart +++ b/packages/flutter/test/gestures/force_press_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('A force press can be recognized', (GestureTester tester) { diff --git a/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart b/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart index 0ea6d959bc7..c7b88406f9e 100644 --- a/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart +++ b/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart @@ -32,7 +32,7 @@ void main() { testWidgets('PointerEvent resampling on a widget', (WidgetTester tester) async { assert(WidgetsBinding.instance == binding); Duration currentTestFrameTime() => Duration(milliseconds: binding.clock.now().millisecondsSinceEpoch); - void requestFrame() => SchedulerBinding.instance!.scheduleFrameCallback((_) {}); + void requestFrame() => SchedulerBinding.instance.scheduleFrameCallback((_) {}); final Duration epoch = currentTestFrameTime(); final ui.PointerDataPacket packet = ui.PointerDataPacket( data: [ @@ -92,9 +92,9 @@ void main() { ), ); - GestureBinding.instance!.resamplingEnabled = true; + GestureBinding.instance.resamplingEnabled = true; const Duration kSamplingOffset = Duration(milliseconds: -5); - GestureBinding.instance!.samplingOffset = kSamplingOffset; + GestureBinding.instance.samplingOffset = kSamplingOffset; ui.window.onPointerDataPacket!(packet); expect(events.length, 0); diff --git a/packages/flutter/test/gestures/gesture_binding_resample_event_test.dart b/packages/flutter/test/gestures/gesture_binding_resample_event_test.dart index 95b134ae13b..e93a17e4ea2 100644 --- a/packages/flutter/test/gestures/gesture_binding_resample_event_test.dart +++ b/packages/flutter/test/gestures/gesture_binding_resample_event_test.dart @@ -117,8 +117,8 @@ void main() { const Duration samplingOffset = Duration(milliseconds: -5); const Duration frameInterval = Duration(microseconds: 16667); - GestureBinding.instance!.resamplingEnabled = true; - GestureBinding.instance!.samplingOffset = samplingOffset; + GestureBinding.instance.resamplingEnabled = true; + GestureBinding.instance.samplingOffset = samplingOffset; final List events = []; binding.callback = events.add; @@ -180,6 +180,6 @@ void main() { // No more pointer events should have been dispatched. expect(events.length, 5); - GestureBinding.instance!.resamplingEnabled = false; + GestureBinding.instance.resamplingEnabled = false; }); } diff --git a/packages/flutter/test/gestures/gesture_binding_test.dart b/packages/flutter/test/gestures/gesture_binding_test.dart index c8143834a1c..02f3b22c845 100644 --- a/packages/flutter/test/gestures/gesture_binding_test.dart +++ b/packages/flutter/test/gestures/gesture_binding_test.dart @@ -12,6 +12,29 @@ import 'package:flutter_test/flutter_test.dart'; typedef HandleEventCallback = void Function(PointerEvent event); class TestGestureFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding { + @override + void initInstances() { + super.initInstances(); + _instance = this; + } + + /// The singleton instance of this object. + /// + /// Provides access to the features exposed by this class. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [TestGestureFlutterBinding.ensureInitialized]. + static TestGestureFlutterBinding get instance => BindingBase.checkInstance(_instance); + static TestGestureFlutterBinding? _instance; + + /// Returns an instance of the [TestGestureFlutterBinding], creating and + /// initializing it if necessary. + static TestGestureFlutterBinding ensureInitialized() { + if (_instance == null) { + TestGestureFlutterBinding(); + } + return _instance!; + } + HandleEventCallback? callback; @override @@ -22,16 +45,8 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding, Schedul } } -TestGestureFlutterBinding? _binding; - -void ensureTestGestureBinding() { - _binding ??= TestGestureFlutterBinding(); - assert(GestureBinding.instance != null); - assert(SchedulerBinding.instance != null); -} - void main() { - setUp(ensureTestGestureBinding); + final TestGestureFlutterBinding _binding = TestGestureFlutterBinding.ensureInitialized(); test('Pointer tap events', () { const ui.PointerDataPacket packet = ui.PointerDataPacket( @@ -42,7 +57,7 @@ void main() { ); final List events = []; - _binding!.callback = events.add; + _binding.callback = events.add; ui.window.onPointerDataPacket?.call(packet); expect(events.length, 2); @@ -60,7 +75,7 @@ void main() { ); final List events = []; - _binding!.callback = events.add; + _binding.callback = events.add; ui.window.onPointerDataPacket?.call(packet); expect(events.length, 3); @@ -82,10 +97,10 @@ void main() { ); final List pointerRouterEvents = []; - GestureBinding.instance!.pointerRouter.addGlobalRoute(pointerRouterEvents.add); + GestureBinding.instance.pointerRouter.addGlobalRoute(pointerRouterEvents.add); final List events = []; - _binding!.callback = events.add; + _binding.callback = events.add; ui.window.onPointerDataPacket?.call(packet); expect(events.length, 3); @@ -110,7 +125,7 @@ void main() { ); final List events = []; - _binding!.callback = events.add; + _binding.callback = events.add; ui.window.onPointerDataPacket?.call(packet); expect(events.length, 2); @@ -127,10 +142,10 @@ void main() { ); final List events = []; - _binding!.callback = (PointerEvent event) { + _binding.callback = (PointerEvent event) { events.add(event); if (event is PointerDownEvent) - _binding!.cancelPointer(event.pointer); + _binding.cancelPointer(event.pointer); }; ui.window.onPointerDataPacket?.call(packet); diff --git a/packages/flutter/test/gestures/gesture_tester.dart b/packages/flutter/test/gestures/gesture_tester.dart index dcbba99ea66..0679d947d02 100644 --- a/packages/flutter/test/gestures/gesture_tester.dart +++ b/packages/flutter/test/gestures/gesture_tester.dart @@ -3,30 +3,21 @@ // found in the LICENSE file. import 'package:fake_async/fake_async.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:meta/meta.dart'; -class TestGestureFlutterBinding extends BindingBase with GestureBinding { } - -void ensureGestureBinding() { - if (GestureBinding.instance == null) - TestGestureFlutterBinding(); - assert(GestureBinding.instance != null); -} - class GestureTester { GestureTester._(this.async); final FakeAsync async; void closeArena(int pointer) { - GestureBinding.instance!.gestureArena.close(pointer); + GestureBinding.instance.gestureArena.close(pointer); } void route(PointerEvent event) { - GestureBinding.instance!.pointerRouter.route(event); + GestureBinding.instance.pointerRouter.route(event); async.flushMicrotasks(); } } diff --git a/packages/flutter/test/gestures/long_press_test.dart b/packages/flutter/test/gestures/long_press_test.dart index a07de9471f1..10adf360588 100644 --- a/packages/flutter/test/gestures/long_press_test.dart +++ b/packages/flutter/test/gestures/long_press_test.dart @@ -59,7 +59,7 @@ const PointerUpEvent up4 = PointerUpEvent( ); void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); group('Long press', () { late LongPressGestureRecognizer gesture; diff --git a/packages/flutter/test/gestures/monodrag_test.dart b/packages/flutter/test/gestures/monodrag_test.dart index 5f3d0db4018..42057341f99 100644 --- a/packages/flutter/test/gestures/monodrag_test.dart +++ b/packages/flutter/test/gestures/monodrag_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('do not crash on up event for a pending pointer after winning arena for another pointer', (GestureTester tester) { // Regression test for https://github.com/flutter/flutter/issues/75061. @@ -39,14 +39,14 @@ void main() { ); v.addPointer(down90); - GestureBinding.instance!.gestureArena.close(90); + GestureBinding.instance.gestureArena.close(90); h.addPointer(down91); v.addPointer(down91); - GestureBinding.instance!.gestureArena.close(91); + GestureBinding.instance.gestureArena.close(91); tester.async.flushMicrotasks(); - GestureBinding.instance!.handleEvent(up90, HitTestEntry(MockHitTestTarget())); - GestureBinding.instance!.handleEvent(up91, HitTestEntry(MockHitTestTarget())); + GestureBinding.instance.handleEvent(up90, HitTestEntry(MockHitTestTarget())); + GestureBinding.instance.handleEvent(up91, HitTestEntry(MockHitTestTarget())); }); testWidgets('VerticalDragGestureRecognizer asserts when kind and supportedDevices are both set', (WidgetTester tester) async { diff --git a/packages/flutter/test/gestures/multidrag_test.dart b/packages/flutter/test/gestures/multidrag_test.dart index d971caaa5cb..5619200a9d4 100644 --- a/packages/flutter/test/gestures/multidrag_test.dart +++ b/packages/flutter/test/gestures/multidrag_test.dart @@ -10,7 +10,7 @@ import 'gesture_tester.dart'; class TestDrag extends Drag { } void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('MultiDrag: moving before delay rejects', (GestureTester tester) { final DelayedMultiDragGestureRecognizer drag = DelayedMultiDragGestureRecognizer(); diff --git a/packages/flutter/test/gestures/multitap_test.dart b/packages/flutter/test/gestures/multitap_test.dart index 7d0a0449e58..23c437bcfcb 100644 --- a/packages/flutter/test/gestures/multitap_test.dart +++ b/packages/flutter/test/gestures/multitap_test.dart @@ -11,7 +11,7 @@ class TestDrag extends Drag { } void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('Should recognize pan', (GestureTester tester) { final MultiTapGestureRecognizer tap = MultiTapGestureRecognizer(longTapDelay: kLongPressTimeout); diff --git a/packages/flutter/test/gestures/recognizer_test.dart b/packages/flutter/test/gestures/recognizer_test.dart index 48fe20eaace..1822f2c740d 100644 --- a/packages/flutter/test/gestures/recognizer_test.dart +++ b/packages/flutter/test/gestures/recognizer_test.dart @@ -42,7 +42,7 @@ const PointerUpEvent up2 = PointerUpEvent( ); void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); test('GestureRecognizer smoketest', () { final TestGestureRecognizer recognizer = TestGestureRecognizer(debugOwner: 0); @@ -213,7 +213,7 @@ class TestGestureRecognizer extends GestureRecognizer { class IndefiniteGestureRecognizer extends GestureRecognizer { @override void addAllowedPointer(PointerDownEvent event) { - GestureBinding.instance!.gestureArena.add(event.pointer, this); + GestureBinding.instance.gestureArena.add(event.pointer, this); } @override diff --git a/packages/flutter/test/gestures/scale_test.dart b/packages/flutter/test/gestures/scale_test.dart index 99f0392d5f4..30df341f601 100644 --- a/packages/flutter/test/gestures/scale_test.dart +++ b/packages/flutter/test/gestures/scale_test.dart @@ -10,7 +10,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('Should recognize scale gestures', (GestureTester tester) { final ScaleGestureRecognizer scale = ScaleGestureRecognizer(); diff --git a/packages/flutter/test/gestures/tap_test.dart b/packages/flutter/test/gestures/tap_test.dart index 2266b5478db..5bd8d86a3e4 100644 --- a/packages/flutter/test/gestures/tap_test.dart +++ b/packages/flutter/test/gestures/tap_test.dart @@ -17,7 +17,7 @@ class TestGestureArenaMember extends GestureArenaMember { } void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); // Down/up pair 1: normal tap sequence const PointerDownEvent down1 = PointerDownEvent( @@ -113,7 +113,7 @@ void main() { tester.route(up1); expect(tapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapRecognized, isTrue); tap.dispose(); @@ -164,7 +164,7 @@ void main() { tester.route(up1); expect(tapsRecognized, 1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapsRecognized, 1); tap.addPointer(down1); @@ -175,7 +175,7 @@ void main() { tester.route(up1); expect(tapsRecognized, 2); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapsRecognized, 2); tap.dispose(); @@ -204,12 +204,12 @@ void main() { tester.route(up1); expect(tapsRecognized, 1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapsRecognized, 1); tester.route(up2); expect(tapsRecognized, 1); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(tapsRecognized, 1); tap.dispose(); @@ -238,12 +238,12 @@ void main() { tester.route(up2); expect(tapsRecognized, 0); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(tapsRecognized, 0); tester.route(up1); expect(tapsRecognized, 1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapsRecognized, 1); tap.dispose(); @@ -275,7 +275,7 @@ void main() { tester.route(up3); expect(tapRecognized, isFalse); expect(tapCanceled, isTrue); - GestureBinding.instance!.gestureArena.sweep(3); + GestureBinding.instance.gestureArena.sweep(3); expect(tapRecognized, isFalse); expect(tapCanceled, isTrue); @@ -308,7 +308,7 @@ void main() { tester.route(up4); expect(tapRecognized, isTrue); expect(tapCanceled, isFalse); - GestureBinding.instance!.gestureArena.sweep(4); + GestureBinding.instance.gestureArena.sweep(4); expect(tapRecognized, isTrue); expect(tapCanceled, isFalse); @@ -333,7 +333,7 @@ void main() { expect(tapRecognized, isFalse); tester.route(up1); expect(tapRecognized, isTrue); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapRecognized, isTrue); tap.dispose(); @@ -349,8 +349,8 @@ void main() { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - final GestureArenaEntry entry = GestureBinding.instance!.gestureArena.add(1, member); - GestureBinding.instance!.gestureArena.hold(1); + final GestureArenaEntry entry = GestureBinding.instance.gestureArena.add(1, member); + GestureBinding.instance.gestureArena.hold(1); tester.closeArena(1); expect(tapRecognized, isFalse); tester.route(down1); @@ -358,7 +358,7 @@ void main() { tester.route(up1); expect(tapRecognized, isFalse); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapRecognized, isFalse); entry.resolve(GestureDisposition.accepted); @@ -377,8 +377,8 @@ void main() { tap.addPointer(down1); final TestGestureArenaMember member = TestGestureArenaMember(); - final GestureArenaEntry entry = GestureBinding.instance!.gestureArena.add(1, member); - GestureBinding.instance!.gestureArena.hold(1); + final GestureArenaEntry entry = GestureBinding.instance.gestureArena.add(1, member); + GestureBinding.instance.gestureArena.hold(1); tester.closeArena(1); expect(tapRecognized, isFalse); tester.route(down1); @@ -386,7 +386,7 @@ void main() { tester.route(up1); expect(tapRecognized, isFalse); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(tapRecognized, isFalse); entry.resolve(GestureDisposition.rejected); @@ -472,7 +472,7 @@ void main() { log.add('routed 1 down'); tester.route(up1); log.add('routed 1 up'); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); log.add('swept 1'); tapA.addPointer(down2); log.add('down 2 to A'); @@ -484,7 +484,7 @@ void main() { log.add('routed 2 down'); tester.route(up2); log.add('routed 2 up'); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); log.add('swept 2'); tapA.dispose(); log.add('disposed A'); @@ -616,7 +616,7 @@ void main() { drag.addPointer(down3); tester.closeArena(3); tester.route(move3); - GestureBinding.instance!.gestureArena.sweep(3); + GestureBinding.instance.gestureArena.sweep(3); expect(recognized, isEmpty); tap.dispose(); @@ -653,7 +653,7 @@ void main() { expect(recognized, isEmpty); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(down1.pointer); + GestureBinding.instance.gestureArena.sweep(down1.pointer); expect(recognized, ['down', 'up', 'tap']); recognized.clear(); @@ -662,7 +662,7 @@ void main() { expect(recognized, isEmpty); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(down2.pointer); + GestureBinding.instance.gestureArena.sweep(down2.pointer); expect(recognized, isEmpty); tap.dispose(); @@ -763,14 +763,14 @@ void main() { tester.route(move1lr); tester.route(move1r); tester.route(up1); - GestureBinding.instance!.gestureArena.sweep(1); + GestureBinding.instance.gestureArena.sweep(1); expect(recognized, ['down', 'cancel']); tap.addPointer(down2); tester.closeArena(2); tester.async.elapse(const Duration(milliseconds: 1000)); tester.route(up2); - GestureBinding.instance!.gestureArena.sweep(2); + GestureBinding.instance.gestureArena.sweep(2); expect(recognized, ['down', 'cancel', 'down', 'up']); tap.dispose(); @@ -940,7 +940,7 @@ void main() { tester.route(up1); expect(recognized, ['primaryUp', 'primary']); - GestureBinding.instance!.gestureArena.sweep(down1.pointer); + GestureBinding.instance.gestureArena.sweep(down1.pointer); }); testGesture('A primary tap cancel trigger primary callbacks', (GestureTester tester) { @@ -953,7 +953,7 @@ void main() { tester.route(cancel1); expect(recognized, ['primaryCancel']); - GestureBinding.instance!.gestureArena.sweep(down1.pointer); + GestureBinding.instance.gestureArena.sweep(down1.pointer); }); testGesture('A secondary tap should trigger secondary callbacks', (GestureTester tester) { @@ -965,7 +965,7 @@ void main() { recognized.clear(); tester.route(up5); - GestureBinding.instance!.gestureArena.sweep(down5.pointer); + GestureBinding.instance.gestureArena.sweep(down5.pointer); expect(recognized, ['secondaryUp']); }); @@ -978,7 +978,7 @@ void main() { recognized.clear(); tester.route(up6); - GestureBinding.instance!.gestureArena.sweep(down6.pointer); + GestureBinding.instance.gestureArena.sweep(down6.pointer); expect(recognized, ['tertiaryUp']); }); @@ -991,7 +991,7 @@ void main() { recognized.clear(); tester.route(cancel5); - GestureBinding.instance!.gestureArena.sweep(down5.pointer); + GestureBinding.instance.gestureArena.sweep(down5.pointer); expect(recognized, ['secondaryCancel']); }); @@ -1004,7 +1004,7 @@ void main() { recognized.clear(); tester.route(cancel6); - GestureBinding.instance!.gestureArena.sweep(down6.pointer); + GestureBinding.instance.gestureArena.sweep(down6.pointer); expect(recognized, ['tertiaryCancel']); }); }); diff --git a/packages/flutter/test/gestures/team_test.dart b/packages/flutter/test/gestures/team_test.dart index 89c9ec957d2..0f6bb55f740 100644 --- a/packages/flutter/test/gestures/team_test.dart +++ b/packages/flutter/test/gestures/team_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'gesture_tester.dart'; void main() { - setUp(ensureGestureBinding); + TestWidgetsFlutterBinding.ensureInitialized(); testGesture('GestureArenaTeam rejection test', (GestureTester tester) { final GestureArenaTeam team = GestureArenaTeam(); diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart index 55bd0fce88a..cad79897543 100644 --- a/packages/flutter/test/material/app_test.dart +++ b/packages/flutter/test/material/app_test.dart @@ -1015,7 +1015,7 @@ void main() { // Simulate android back button intent. final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); }); diff --git a/packages/flutter/test/material/bottom_navigation_bar_test.dart b/packages/flutter/test/material/bottom_navigation_bar_test.dart index f94c5b971e9..8d62fcff817 100644 --- a/packages/flutter/test/material/bottom_navigation_bar_test.dart +++ b/packages/flutter/test/material/bottom_navigation_bar_test.dart @@ -1835,7 +1835,7 @@ void main() { await tester.pumpAndSettle(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -1854,7 +1854,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); group('feedback', () { diff --git a/packages/flutter/test/material/checkbox_test.dart b/packages/flutter/test/material/checkbox_test.dart index 6c03f41aad4..688fbf239bd 100644 --- a/packages/flutter/test/material/checkbox_test.dart +++ b/packages/flutter/test/material/checkbox_test.dart @@ -714,7 +714,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -736,7 +736,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -758,7 +758,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); // Test cursor when tristate await tester.pumpWidget( @@ -782,7 +782,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); await tester.pumpAndSettle(); }); diff --git a/packages/flutter/test/material/checkbox_theme_test.dart b/packages/flutter/test/material/checkbox_theme_test.dart index bcd7f0cb5d4..bbb63c4545a 100644 --- a/packages/flutter/test/material/checkbox_theme_test.dart +++ b/packages/flutter/test/material/checkbox_theme_test.dart @@ -145,7 +145,7 @@ void main() { await tester.pumpWidget(buildCheckbox()); await _pointGestureToCheckbox(tester); await tester.pumpAndSettle(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(_getCheckboxMaterial(tester), paints..circle(color: hoverOverlayColor)); // Checkbox with focus. @@ -244,7 +244,7 @@ void main() { await tester.pumpWidget(buildCheckbox()); await _pointGestureToCheckbox(tester); await tester.pumpAndSettle(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(_getCheckboxMaterial(tester), paints..circle(color: hoverColor)); // Checkbox with focus. diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 9c23cd249f5..596d2aac5f1 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -1266,7 +1266,7 @@ void main() { // Simulate a tap on the label to select the chip. await tester.tap(find.byKey(labelKey)); expect(selected, equals(true)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01)); @@ -1284,7 +1284,7 @@ void main() { // Simulate another tap on the label to deselect the chip. await tester.tap(find.byKey(labelKey)); expect(selected, equals(false)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(); await tester.pump(const Duration(milliseconds: 20)); expect(getSelectProgress(tester), moreOrLessEquals(0.875, epsilon: 0.01)); @@ -1342,7 +1342,7 @@ void main() { // Simulate a tap on the label to select the chip. await tester.tap(find.byKey(labelKey)); expect(selected, equals(true)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01)); @@ -1360,7 +1360,7 @@ void main() { // Simulate another tap on the label to deselect the chip. await tester.tap(find.byKey(labelKey)); expect(selected, equals(false)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(); await tester.pump(const Duration(milliseconds: 20)); expect(getSelectProgress(tester), moreOrLessEquals(0.875, epsilon: 0.01)); @@ -1417,7 +1417,7 @@ void main() { await tester.tap(find.byKey(labelKey)); expect(selected, equals(true)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01)); diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart index 491ae4cb113..d2131167ac5 100644 --- a/packages/flutter/test/material/dropdown_test.dart +++ b/packages/flutter/test/material/dropdown_test.dart @@ -3423,9 +3423,9 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); await gesture.moveTo(offDropdownButton); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); // Test that mouse cursor doesn't change when button is disabled await tester.pumpWidget( @@ -3446,9 +3446,9 @@ void main() { ); await gesture.moveTo(onDropdownButton); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await gesture.moveTo(offDropdownButton); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('Conflicting scrollbars are not applied by ScrollBehavior to Dropdown', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/flat_button_test.dart b/packages/flutter/test/material/flat_button_test.dart index c2739ab71b1..c43ff902b21 100644 --- a/packages/flutter/test/material/flat_button_test.dart +++ b/packages/flutter/test/material/flat_button_test.dart @@ -458,7 +458,7 @@ void main() { addTearDown(gesture.removePointer); await tester.pump(); - expect(RendererBinding.instance?.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await tester.pumpWidget( Directionality( @@ -474,7 +474,7 @@ void main() { ), ); - expect(RendererBinding.instance?.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -490,7 +490,7 @@ void main() { ), ); - expect(RendererBinding.instance?.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -506,7 +506,7 @@ void main() { ), ); - expect(RendererBinding.instance?.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('Does FlatButton work with focus', (WidgetTester tester) async { @@ -525,7 +525,7 @@ void main() { ), ); - WidgetsBinding.instance?.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; + WidgetsBinding.instance.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; focusNode.requestFocus(); await tester.pumpAndSettle(); diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index be4bad1d59e..b75d7fe7637 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -812,7 +812,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await tester.pumpWidget( MaterialApp( @@ -830,7 +830,7 @@ void main() { ); await gesture.moveTo(tester.getCenter(find.byType(FloatingActionButton))); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -847,7 +847,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -864,7 +864,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('Floating Action Button has no clip by default', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart index 01c4a6f3002..1590cbd34ed 100644 --- a/packages/flutter/test/material/icon_button_test.dart +++ b/packages/flutter/test/material/icon_button_test.dart @@ -661,7 +661,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); // Test default is click await tester.pumpWidget( @@ -678,7 +678,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); } diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart index 7dbf405d16d..24bbf72a8f1 100644 --- a/packages/flutter/test/material/ink_well_test.dart +++ b/packages/flutter/test/material/ink_well_test.dart @@ -433,7 +433,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default of InkWell() await tester.pumpWidget( @@ -450,7 +450,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test disabled await tester.pumpWidget( @@ -465,7 +465,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); // Test default of InkResponse() await tester.pumpWidget( @@ -482,7 +482,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test disabled await tester.pumpWidget( @@ -497,7 +497,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); group('feedback', () { diff --git a/packages/flutter/test/material/list_tile_test.dart b/packages/flutter/test/material/list_tile_test.dart index b1bcf64e88b..27e3615a95e 100644 --- a/packages/flutter/test/material/list_tile_test.dart +++ b/packages/flutter/test/material/list_tile_test.dart @@ -1570,7 +1570,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -1588,7 +1588,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -1606,7 +1606,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); // Test default cursor when onTap or onLongPress is null await tester.pumpWidget( @@ -1622,7 +1622,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('ListTile respects tileColor & selectedTileColor', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/material_button_test.dart b/packages/flutter/test/material/material_button_test.dart index 46f2ef797f3..f5c4f7cf30e 100644 --- a/packages/flutter/test/material/material_button_test.dart +++ b/packages/flutter/test/material/material_button_test.dart @@ -393,7 +393,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -408,7 +408,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -423,7 +423,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); // This test is very similar to the '...explicit splashColor and highlightColor' test diff --git a/packages/flutter/test/material/outline_button_test.dart b/packages/flutter/test/material/outline_button_test.dart index 434760bca26..3bf84022f10 100644 --- a/packages/flutter/test/material/outline_button_test.dart +++ b/packages/flutter/test/material/outline_button_test.dart @@ -130,7 +130,7 @@ void main() { addTearDown(gesture.removePointer); await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await tester.pumpWidget( Directionality( @@ -145,7 +145,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -160,7 +160,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -175,7 +175,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('Does OutlineButton work with focus', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/page_test.dart b/packages/flutter/test/material/page_test.dart index 2cded91e640..463ef588245 100644 --- a/packages/flutter/test/material/page_test.dart +++ b/packages/flutter/test/material/page_test.dart @@ -999,7 +999,7 @@ Widget buildNavigator({ TransitionDelegate? transitionDelegate, }) { return MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ diff --git a/packages/flutter/test/material/paginated_data_table_test.dart b/packages/flutter/test/material/paginated_data_table_test.dart index 5e0c60eb611..eea878fbe14 100644 --- a/packages/flutter/test/material/paginated_data_table_test.dart +++ b/packages/flutter/test/material/paginated_data_table_test.dart @@ -64,7 +64,7 @@ class TestDataSource extends DataTableSource { void main() { final TestWidgetsFlutterBinding binding = - TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + TestWidgetsFlutterBinding.ensureInitialized(); testWidgets('PaginatedDataTable paging', (WidgetTester tester) async { final TestDataSource source = TestDataSource(); diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index fe9e6c277cf..b7e282209e1 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -1984,7 +1984,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -2007,7 +2007,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -2031,7 +2031,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('PopupMenu in AppBar does not overlap with the status bar', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/radio_test.dart b/packages/flutter/test/material/radio_test.dart index 048e1470c4c..b349b69b729 100644 --- a/packages/flutter/test/material/radio_test.dart +++ b/packages/flutter/test/material/radio_test.dart @@ -704,7 +704,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor @@ -728,7 +728,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -751,7 +751,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('Radio button fill color resolves in enabled/disabled states', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/radio_theme_test.dart b/packages/flutter/test/material/radio_theme_test.dart index 3026fc4bd17..78373c54544 100644 --- a/packages/flutter/test/material/radio_theme_test.dart +++ b/packages/flutter/test/material/radio_theme_test.dart @@ -134,7 +134,7 @@ void main() { await _pointGestureToRadio(tester); await tester.pumpAndSettle(); expect(_getRadioMaterial(tester), paints..circle(color: hoverOverlayColor)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Radio with focus. await tester.pumpWidget(buildRadio(autofocus: true)); @@ -228,7 +228,7 @@ void main() { await _pointGestureToRadio(tester); await tester.pumpAndSettle(); expect(_getRadioMaterial(tester), paints..circle(color: hoverColor)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Radio with focus. await tester.pumpWidget(buildRadio(autofocus: true)); diff --git a/packages/flutter/test/material/raised_button_test.dart b/packages/flutter/test/material/raised_button_test.dart index afd27e4d47c..fba11838db8 100644 --- a/packages/flutter/test/material/raised_button_test.dart +++ b/packages/flutter/test/material/raised_button_test.dart @@ -452,7 +452,7 @@ void main() { addTearDown(gesture.removePointer); await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await tester.pumpWidget( Directionality( @@ -467,7 +467,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -482,7 +482,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -497,7 +497,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); diff --git a/packages/flutter/test/material/raw_material_button_test.dart b/packages/flutter/test/material/raw_material_button_test.dart index 27f6f602054..74269320f42 100644 --- a/packages/flutter/test/material/raw_material_button_test.dart +++ b/packages/flutter/test/material/raw_material_button_test.dart @@ -593,7 +593,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -608,7 +608,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -623,6 +623,6 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); } diff --git a/packages/flutter/test/material/scrollbar_test.dart b/packages/flutter/test/material/scrollbar_test.dart index 97b7facd969..529dfdc0b46 100644 --- a/packages/flutter/test/material/scrollbar_test.dart +++ b/packages/flutter/test/material/scrollbar_test.dart @@ -94,15 +94,15 @@ void main() { ), ); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Building a list with a scrollbar triggered an animation.'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Building a list with a scrollbar triggered an animation.'); await tester.tap(find.byType(ListView)); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Tapping a block with a scrollbar triggered an animation.'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Tapping a block with a scrollbar triggered an animation.'); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.drag(find.byType(ListView), const Offset(0.0, -10.0)); - expect(SchedulerBinding.instance!.transientCallbackCount, greaterThan(0)); + expect(SchedulerBinding.instance.transientCallbackCount, greaterThan(0)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart index f3e38a50c8b..49ad3934db1 100644 --- a/packages/flutter/test/material/search_test.dart +++ b/packages/flutter/test/material/search_test.dart @@ -124,7 +124,7 @@ void main() { // Simulate system back button final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(selectedResults, [null]); diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index 26ef3d60ee3..95cc9180640 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -119,7 +119,7 @@ void main() { startValue = null; endValue = null; await tester.pump(); // No animation should start. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey)); final Offset bottomRight = tester.getBottomRight(find.byKey(sliderKey)); @@ -130,7 +130,7 @@ void main() { expect(startValue, equals(0.5)); expect(endValue, moreOrLessEquals(0.25, epsilon: 0.05)); await tester.pump(); // No animation should start. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider can move when tapped (RTL)', (WidgetTester tester) async { @@ -169,7 +169,7 @@ void main() { await tester.tap(find.byKey(sliderKey)); expect(value, equals(0.5)); await tester.pump(); // No animation should start. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey)); final Offset bottomRight = tester.getBottomRight(find.byKey(sliderKey)); @@ -178,7 +178,7 @@ void main() { await tester.tapAt(target); expect(value, moreOrLessEquals(0.75, epsilon: 0.05)); await tester.pump(); // No animation should start. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets("Slider doesn't send duplicate change events if tapped on the same value", (WidgetTester tester) async { @@ -280,19 +280,19 @@ void main() { expect(value, equals(0.5)); await tester.pump(const Duration(milliseconds: 100)); // Starts with the position animation and value indicator - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); await tester.pump(const Duration(milliseconds: 100)); // Value indicator is longer than position. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); await tester.pump(const Duration(milliseconds: 100)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.pump(const Duration(milliseconds: 100)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); await tester.pump(const Duration(milliseconds: 100)); // Shown for long enough, value indicator is animated closed. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); await tester.pump(const Duration(milliseconds: 101)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Discrete Slider repaints and animates when dragged', (WidgetTester tester) async { @@ -528,13 +528,13 @@ void main() { expect(value, equals(80.0)); await tester.pump(); // Starts animation. - expect(SchedulerBinding.instance!.transientCallbackCount, greaterThan(0)); + expect(SchedulerBinding.instance.transientCallbackCount, greaterThan(0)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200)); // Animation complete. - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); testWidgets('Slider can be given zero values', (WidgetTester tester) async { @@ -1265,7 +1265,7 @@ void main() { await tester.pump(); await gesture.up(); await tester.pumpAndSettle(); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); expect( material, paints @@ -1281,7 +1281,7 @@ void main() { await tester.pump(); // Wait for animations to start. await tester.pump(const Duration(milliseconds: 25)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); expect( material, paints @@ -1301,7 +1301,7 @@ void main() { // Move a little further in the animations. await tester.pump(const Duration(milliseconds: 10)); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(2)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(2)); expect( material, paints @@ -1315,7 +1315,7 @@ void main() { ); // Wait for animations to finish. await tester.pumpAndSettle(); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); expect( material, paints @@ -1329,7 +1329,7 @@ void main() { ); await gesture.up(); await tester.pumpAndSettle(); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0)); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); expect( material, paints @@ -2319,7 +2319,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test Slider.adaptive() constructor await tester.pumpWidget( @@ -2342,7 +2342,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -2364,7 +2364,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); testWidgets('Slider implements debugFillProperties', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart index e0e968f5e09..ab4369f133a 100644 --- a/packages/flutter/test/material/switch_test.dart +++ b/packages/flutter/test/material/switch_test.dart @@ -1023,7 +1023,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test Switch() constructor await tester.pumpWidget( @@ -1047,7 +1047,7 @@ void main() { ); await gesture.moveTo(tester.getCenter(find.byType(Switch))); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -1069,7 +1069,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -1091,7 +1091,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await tester.pumpAndSettle(); }); diff --git a/packages/flutter/test/material/switch_theme_test.dart b/packages/flutter/test/material/switch_theme_test.dart index 7943e222c3d..b6432beb79c 100644 --- a/packages/flutter/test/material/switch_theme_test.dart +++ b/packages/flutter/test/material/switch_theme_test.dart @@ -155,7 +155,7 @@ void main() { await tester.pumpWidget(buildSwitch()); await _pointGestureToSwitch(tester); await tester.pumpAndSettle(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(_getSwitchMaterial(tester), paints..circle(color: hoverOverlayColor)); // Switch with focus. @@ -276,7 +276,7 @@ void main() { await tester.pumpWidget(buildSwitch()); await _pointGestureToSwitch(tester); await tester.pumpAndSettle(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(_getSwitchMaterial(tester), paints..circle(color: hoverColor)); // Switch with focus. diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index e002c11feb9..87cfcac8086 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -2613,7 +2613,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget(MaterialApp(home: DefaultTabController( @@ -2628,7 +2628,7 @@ void main() { ), ), )); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); testWidgets('TabController changes', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/text_button_test.dart b/packages/flutter/test/material/text_button_test.dart index 7600449849b..d4ce04ab9f4 100644 --- a/packages/flutter/test/material/text_button_test.dart +++ b/packages/flutter/test/material/text_button_test.dart @@ -467,7 +467,7 @@ void main() { ), ); - WidgetsBinding.instance!.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; + WidgetsBinding.instance.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; focusNode.requestFocus(); await tester.pumpAndSettle(); diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 4e70625882b..16071b52325 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -9507,7 +9507,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); // Test default cursor await tester.pumpWidget( @@ -9525,9 +9525,9 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await gesture.moveTo(edge); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await gesture.moveTo(center); // Test default cursor when disabled @@ -9547,9 +9547,9 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await gesture.moveTo(edge); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await gesture.moveTo(center); }); diff --git a/packages/flutter/test/material/toggle_buttons_test.dart b/packages/flutter/test/material/toggle_buttons_test.dart index 22e2227b539..b7728cab96f 100644 --- a/packages/flutter/test/material/toggle_buttons_test.dart +++ b/packages/flutter/test/material/toggle_buttons_test.dart @@ -1729,7 +1729,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default cursor await tester.pumpWidget( @@ -1750,7 +1750,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor when disabled await tester.pumpWidget( @@ -1770,7 +1770,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('ToggleButtons focus, hover, and highlight elevations are 0', (WidgetTester tester) async { diff --git a/packages/flutter/test/painting/binding_test.dart b/packages/flutter/test/painting/binding_test.dart index 3c3f0fa9189..1a1300a3345 100644 --- a/packages/flutter/test/painting/binding_test.dart +++ b/packages/flutter/test/painting/binding_test.dart @@ -15,7 +15,7 @@ Future main() async { final ui.Image image = await createTestImage(); testWidgets('didHaveMemoryPressure clears imageCache', (WidgetTester tester) async { - imageCache!.putIfAbsent(1, () => OneFrameImageStreamCompleter( + imageCache.putIfAbsent(1, () => OneFrameImageStreamCompleter( Future.value(ImageInfo( image: image, scale: 1.0, @@ -23,10 +23,10 @@ Future main() async { )); await tester.idle(); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); final ByteData message = const JSONMessageCodec().encodeMessage({'type': 'memoryPressure'})!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/system', message, (_) { }); - expect(imageCache!.currentSize, 0); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/system', message, (_) { }); + expect(imageCache.currentSize, 0); }); test('evict clears live references', () async { diff --git a/packages/flutter/test/painting/image_cache_binding_test.dart b/packages/flutter/test/painting/image_cache_binding_test.dart index e8a7ce99517..7fcf3f62098 100644 --- a/packages/flutter/test/painting/image_cache_binding_test.dart +++ b/packages/flutter/test/painting/image_cache_binding_test.dart @@ -12,69 +12,36 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - test('PaintingBinding with memory pressure before initInstances', () { - // Observed in devicelab: the device sends a memory pressure event to us - // after PaintingBinding has been created but before initInstances called, - // meaning the imageCache member is still null. - final PaintingBinding binding = TestPaintingBinding(); - expect(binding.imageCache, null); - binding.handleMemoryPressure(); - expect(binding.imageCache, null); - binding.initInstances(); + test('PaintingBinding with memory pressure before initInstances', () async { + // Observed in devicelab: the device sends a memory pressure event + // to us before the binding is initialized, so as soon as the + // ServicesBinding's initInstances sets up the callbacks, we get a + // call. Previously this would happen synchronously during + // initInstances (and before the imageCache was initialized, which + // was a problem), but now it happens asynchronously just after. + + ui.channelBuffers.push(SystemChannels.system.name, SystemChannels.system.codec.encodeMessage({ + 'type': 'memoryPressure', + }), (ByteData? responseData) { + print(SystemChannels.system.codec.decodeMessage(responseData)); + }); + + final TestPaintingBinding binding = TestPaintingBinding(); + expect(binding._handled, isFalse); expect(binding.imageCache, isNotNull); - expect(binding.imageCache!.currentSize, 0); + expect(binding.imageCache.currentSize, 0); + + await null; // allow microtasks to run + expect(binding._handled, isTrue); }); } -class TestBindingBase implements BindingBase { +class TestPaintingBinding extends BindingBase with SchedulerBinding, ServicesBinding, PaintingBinding { @override - void initInstances() {} - - @override - void initServiceExtensions() {} - - @override - Future lockEvents(Future Function() callback) async {} - - @override - bool get locked => throw UnimplementedError(); - - @override - Future performReassemble() { - throw UnimplementedError(); + void handleMemoryPressure() { + super.handleMemoryPressure(); + _handled = true; } - @override - void postEvent(String eventKind, Map eventData) {} - - @override - Future reassembleApplication() { - throw UnimplementedError(); - } - - @override - void registerBoolServiceExtension({required String name, required AsyncValueGetter getter, required AsyncValueSetter setter}) {} - - @override - void registerNumericServiceExtension({required String name, required AsyncValueGetter getter, required AsyncValueSetter setter}) {} - - @override - void registerServiceExtension({required String name, required ServiceExtensionCallback callback}) {} - - @override - void registerSignalServiceExtension({required String name, required AsyncCallback callback}) {} - - @override - void registerStringServiceExtension({required String name, required AsyncValueGetter getter, required AsyncValueSetter setter}) {} - - @override - void unlocked() {} - - @override - ui.SingletonFlutterWindow get window => TestWindow(window: ui.window); - - @override - ui.PlatformDispatcher get platformDispatcher => TestWindow(window: ui.window).platformDispatcher; + bool _handled = false; } - -class TestPaintingBinding extends TestBindingBase with SchedulerBinding, ServicesBinding, PaintingBinding { } diff --git a/packages/flutter/test/painting/image_cache_clearing_test.dart b/packages/flutter/test/painting/image_cache_clearing_test.dart index 5e346816a96..7aef232c1e4 100644 --- a/packages/flutter/test/painting/image_cache_clearing_test.dart +++ b/packages/flutter/test/painting/image_cache_clearing_test.dart @@ -25,7 +25,7 @@ void main() { completer.complete(); }, )); - imageCache!.clearLiveImages(); + imageCache.clearLiveImages(); await completer.future; }); } diff --git a/packages/flutter/test/painting/image_cache_resize_test.dart b/packages/flutter/test/painting/image_cache_resize_test.dart index 806e7735ad0..390ffc9e83a 100644 --- a/packages/flutter/test/painting/image_cache_resize_test.dart +++ b/packages/flutter/test/painting/image_cache_resize_test.dart @@ -14,14 +14,14 @@ void main() { TestRenderingFlutterBinding(); tearDown(() { - imageCache! + imageCache ..clear() ..maximumSize = 1000 ..maximumSizeBytes = 10485760; }); test('Image cache resizing based on count', () async { - imageCache!.maximumSize = 2; + imageCache.maximumSize = 2; final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; final TestImageInfo b = await extractOneFrame(TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; @@ -32,7 +32,7 @@ void main() { expect(c.value, equals(3)); expect(d.value, equals(4)); - imageCache!.maximumSize = 0; + imageCache.maximumSize = 0; final TestImageInfo e = await extractOneFrame(TestImageProvider(1, 5, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(e.value, equals(5)); @@ -40,7 +40,7 @@ void main() { final TestImageInfo f = await extractOneFrame(TestImageProvider(1, 6, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(f.value, equals(6)); - imageCache!.maximumSize = 3; + imageCache.maximumSize = 3; final TestImageInfo g = await extractOneFrame(TestImageProvider(1, 7, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(g.value, equals(7)); @@ -51,7 +51,7 @@ void main() { test('Image cache resizing based on size', () async { final ui.Image testImage = await createTestImage(width: 8, height: 8); // 256 B. - imageCache!.maximumSizeBytes = 256 * 2; + imageCache.maximumSizeBytes = 256 * 2; final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo; final TestImageInfo b = await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo; @@ -62,7 +62,7 @@ void main() { expect(c.value, equals(3)); expect(d.value, equals(4)); - imageCache!.maximumSizeBytes = 0; + imageCache.maximumSizeBytes = 0; final TestImageInfo e = await extractOneFrame(TestImageProvider(1, 5, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(e.value, equals(5)); @@ -70,7 +70,7 @@ void main() { final TestImageInfo f = await extractOneFrame(TestImageProvider(1, 6, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(f.value, equals(6)); - imageCache!.maximumSizeBytes = 256 * 3; + imageCache.maximumSizeBytes = 256 * 3; final TestImageInfo g = await extractOneFrame(TestImageProvider(1, 7, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(g.value, equals(7)); diff --git a/packages/flutter/test/painting/image_cache_test.dart b/packages/flutter/test/painting/image_cache_test.dart index 2b70b8fb262..452640ea0e5 100644 --- a/packages/flutter/test/painting/image_cache_test.dart +++ b/packages/flutter/test/painting/image_cache_test.dart @@ -17,7 +17,7 @@ void main() { TestRenderingFlutterBinding(); tearDown(() { - imageCache! + imageCache ..clear() ..clearLiveImages() ..maximumSize = 1000 @@ -25,7 +25,7 @@ void main() { }); test('maintains cache size', () async { - imageCache!.maximumSize = 3; + imageCache.maximumSize = 3; final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo; expect(a.value, equals(1)); @@ -98,19 +98,19 @@ void main() { test('clear removes all images and resets cache size', () async { final ui.Image testImage = await createTestImage(width: 8, height: 8); - expect(imageCache!.currentSize, 0); - expect(imageCache!.currentSizeBytes, 0); + expect(imageCache.currentSize, 0); + expect(imageCache.currentSizeBytes, 0); await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)); await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty)); - expect(imageCache!.currentSize, 2); - expect(imageCache!.currentSizeBytes, 256 * 2); + expect(imageCache.currentSize, 2); + expect(imageCache.currentSizeBytes, 256 * 2); - imageCache!.clear(); + imageCache.clear(); - expect(imageCache!.currentSize, 0); - expect(imageCache!.currentSizeBytes, 0); + expect(imageCache.currentSize, 0); + expect(imageCache.currentSizeBytes, 0); }); test('evicts individual images', () async { @@ -118,31 +118,31 @@ void main() { await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)); await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty)); - expect(imageCache!.currentSize, 2); - expect(imageCache!.currentSizeBytes, 256 * 2); - expect(imageCache!.evict(1), true); - expect(imageCache!.currentSize, 1); - expect(imageCache!.currentSizeBytes, 256); + expect(imageCache.currentSize, 2); + expect(imageCache.currentSizeBytes, 256 * 2); + expect(imageCache.evict(1), true); + expect(imageCache.currentSize, 1); + expect(imageCache.currentSizeBytes, 256); }); test('Do not cache large images', () async { final ui.Image testImage = await createTestImage(width: 8, height: 8); - imageCache!.maximumSizeBytes = 1; + imageCache.maximumSizeBytes = 1; await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)); - expect(imageCache!.currentSize, 0); - expect(imageCache!.currentSizeBytes, 0); - expect(imageCache!.maximumSizeBytes, 1); + expect(imageCache.currentSize, 0); + expect(imageCache.currentSizeBytes, 0); + expect(imageCache.maximumSizeBytes, 1); }); test('Returns null if an error is caught resolving an image', () { Future _basicDecoder(Uint8List bytes, {int? cacheWidth, int? cacheHeight, bool? allowUpscaling}) { - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); } final ErrorImageProvider errorImage = ErrorImageProvider(); - expect(() => imageCache!.putIfAbsent(errorImage, () => errorImage.load(errorImage, _basicDecoder)), throwsA(isA())); + expect(() => imageCache.putIfAbsent(errorImage, () => errorImage.load(errorImage, _basicDecoder)), throwsA(isA())); bool caughtError = false; - final ImageStreamCompleter? result = imageCache!.putIfAbsent( + final ImageStreamCompleter? result = imageCache.putIfAbsent( errorImage, () => errorImage.load(errorImage, _basicDecoder), onError: (dynamic error, StackTrace? stackTrace) { @@ -159,10 +159,10 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); final TestImageStreamCompleter completer2 = TestImageStreamCompleter(); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; - final TestImageStreamCompleter resultingCompleter2 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter2 = imageCache.putIfAbsent(testImage, () { return completer2; })! as TestImageStreamCompleter; @@ -176,20 +176,20 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); final TestImageStreamCompleter completer2 = TestImageStreamCompleter(); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; - expect(imageCache!.statusForKey(testImage).pending, true); - expect(imageCache!.statusForKey(testImage).live, true); - imageCache!.clear(); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - imageCache!.clearLiveImages(); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, false); + expect(imageCache.statusForKey(testImage).pending, true); + expect(imageCache.statusForKey(testImage).live, true); + imageCache.clear(); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + imageCache.clearLiveImages(); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, false); - final TestImageStreamCompleter resultingCompleter2 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter2 = imageCache.putIfAbsent(testImage, () { return completer2; })! as TestImageStreamCompleter; @@ -203,13 +203,13 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); final TestImageStreamCompleter completer2 = TestImageStreamCompleter(); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; - imageCache!.evict(testImage); + imageCache.evict(testImage); - final TestImageStreamCompleter resultingCompleter2 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter2 = imageCache.putIfAbsent(testImage, () { return completer2; })! as TestImageStreamCompleter; @@ -227,7 +227,7 @@ void main() { fail('Image should not complete successfully'); }, onError: (dynamic exception, StackTrace? stackTrace) { - final bool evictionResult = imageCache!.evict(1); + final bool evictionResult = imageCache.evict(1); expect(evictionResult, isTrue); }, )); @@ -240,12 +240,12 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; expect(resultingCompleter1, completer1); - expect(imageCache!.containsKey(testImage), true); + expect(imageCache.containsKey(testImage), true); }); test('containsKey - completed', () async { @@ -253,7 +253,7 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; @@ -261,11 +261,11 @@ void main() { completer1.testSetImage(testImage); expect(resultingCompleter1, completer1); - expect(imageCache!.containsKey(testImage), true); + expect(imageCache.containsKey(testImage), true); }); test('putIfAbsent updates LRU properties of a live image', () async { - imageCache!.maximumSize = 1; + imageCache.maximumSize = 1; final ui.Image testImage = await createTestImage(width: 8, height: 8); final ui.Image testImage2 = await createTestImage(width: 10, height: 10); @@ -274,32 +274,32 @@ void main() { completer1.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {})); - final TestImageStreamCompleter resultingCompleter1 = imageCache!.putIfAbsent(testImage, () { + final TestImageStreamCompleter resultingCompleter1 = imageCache.putIfAbsent(testImage, () { return completer1; })! as TestImageStreamCompleter; - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).keepAlive, true); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage2).untracked, true); - final TestImageStreamCompleter resultingCompleter2 = imageCache!.putIfAbsent(testImage2, () { + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).keepAlive, true); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage2).untracked, true); + final TestImageStreamCompleter resultingCompleter2 = imageCache.putIfAbsent(testImage2, () { return completer2; })! as TestImageStreamCompleter; - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).keepAlive, false); // evicted - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage2).pending, false); - expect(imageCache!.statusForKey(testImage2).keepAlive, true); // took the LRU spot. - expect(imageCache!.statusForKey(testImage2).live, false); // no listeners + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).keepAlive, false); // evicted + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage2).pending, false); + expect(imageCache.statusForKey(testImage2).keepAlive, true); // took the LRU spot. + expect(imageCache.statusForKey(testImage2).live, false); // no listeners expect(resultingCompleter1, completer1); expect(resultingCompleter2, completer2); }); test('Live image cache avoids leaks of unlistened streams', () async { - imageCache!.maximumSize = 3; + imageCache.maximumSize = 3; TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty); TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty); @@ -311,12 +311,12 @@ void main() { // wait an event loop to let image resolution process. await null; - expect(imageCache!.currentSize, 3); - expect(imageCache!.liveImageCount, 0); + expect(imageCache.currentSize, 3); + expect(imageCache.liveImageCount, 0); }); test('Disabled image cache does not leak live images', () async { - imageCache!.maximumSize = 0; + imageCache.maximumSize = 0; TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty); TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty); @@ -328,8 +328,8 @@ void main() { // wait an event loop to let image resolution process. await null; - expect(imageCache!.currentSize, 0); - expect(imageCache!.liveImageCount, 0); + expect(imageCache.currentSize, 0); + expect(imageCache.liveImageCount, 0); }); test('Evicting a pending image clears the live image by default', () async { @@ -337,13 +337,13 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, true); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, true); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); - imageCache!.evict(testImage); - expect(imageCache!.statusForKey(testImage).untracked, true); + imageCache.evict(testImage); + expect(imageCache.statusForKey(testImage).untracked, true); }); test('Evicting a pending image does clear the live image when includeLive is false and only cache listening', () async { @@ -351,15 +351,15 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, true); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, true); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); - imageCache!.evict(testImage, includeLive: false); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, false); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.evict(testImage, includeLive: false); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, false); + expect(imageCache.statusForKey(testImage).keepAlive, false); }); test('Evicting a pending image does clear the live image when includeLive is false and some other listener', () async { @@ -367,16 +367,16 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, true); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, true); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); completer1.addListener(ImageStreamListener((_, __) {})); - imageCache!.evict(testImage, includeLive: false); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.evict(testImage, includeLive: false); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); }); test('Evicting a completed image does clear the live image by default', () async { @@ -386,13 +386,13 @@ void main() { ..testSetImage(testImage) ..addListener(ImageStreamListener((ImageInfo info, bool syncCall) {})); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); - imageCache!.evict(testImage); - expect(imageCache!.statusForKey(testImage).untracked, true); + imageCache.evict(testImage); + expect(imageCache.statusForKey(testImage).untracked, true); }); test('Evicting a completed image does not clear the live image when includeLive is set to false', () async { @@ -402,15 +402,15 @@ void main() { ..testSetImage(testImage) ..addListener(ImageStreamListener((ImageInfo info, bool syncCall) {})); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); - imageCache!.evict(testImage, includeLive: false); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.evict(testImage, includeLive: false); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); }); test('Clearing liveImages removes callbacks', () async { @@ -426,27 +426,27 @@ void main() { ..testSetImage(testImage) ..addListener(listener); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); - imageCache!.clear(); - imageCache!.clearLiveImages(); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, false); - expect(imageCache!.statusForKey(testImage).keepAlive, false); + imageCache.clear(); + imageCache.clearLiveImages(); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, false); + expect(imageCache.statusForKey(testImage).keepAlive, false); - imageCache!.putIfAbsent(testImage, () => completer2); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); + imageCache.putIfAbsent(testImage, () => completer2); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); completer1.removeListener(listener); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); }); test('Live image gets size updated', () async { @@ -465,32 +465,32 @@ void main() { final TestImageStreamCompleter completer1 = TestImageStreamCompleter() ..addListener(listener); - imageCache!.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, true); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); - expect(imageCache!.currentSizeBytes, 0); + imageCache.putIfAbsent(testImage, () => completer1); + expect(imageCache.statusForKey(testImage).pending, true); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); + expect(imageCache.currentSizeBytes, 0); completer1.testSetImage(testImage); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); - expect(imageCache!.currentSizeBytes, testImageSize); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); + expect(imageCache.currentSizeBytes, testImageSize); - imageCache!.evict(testImage, includeLive: false); + imageCache.evict(testImage, includeLive: false); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, false); - expect(imageCache!.currentSizeBytes, 0); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, false); + expect(imageCache.currentSizeBytes, 0); - imageCache!.putIfAbsent(testImage, () => completer1); + imageCache.putIfAbsent(testImage, () => completer1); - expect(imageCache!.statusForKey(testImage).pending, false); - expect(imageCache!.statusForKey(testImage).live, true); - expect(imageCache!.statusForKey(testImage).keepAlive, true); - expect(imageCache!.currentSizeBytes, testImageSize); + expect(imageCache.statusForKey(testImage).pending, false); + expect(imageCache.statusForKey(testImage).live, true); + expect(imageCache.statusForKey(testImage).keepAlive, true); + expect(imageCache.currentSizeBytes, testImageSize); }); test('Image is obtained and disposed of properly for cache', () async { @@ -506,7 +506,7 @@ void main() { final TestImageStreamCompleter completer = TestImageStreamCompleter(); completer.addListener(listener); - imageCache!.putIfAbsent(key, () => completer); + imageCache.putIfAbsent(key, () => completer); expect(testImage.debugGetOpenHandleStackTraces()!.length, 1); @@ -519,16 +519,16 @@ void main() { completer.removeListener(listener); // Force us to the end of the frame. - SchedulerBinding.instance!.scheduleFrame(); - await SchedulerBinding.instance!.endOfFrame; + SchedulerBinding.instance.scheduleFrame(); + await SchedulerBinding.instance.endOfFrame; expect(testImage.debugGetOpenHandleStackTraces()!.length, 2); - expect(imageCache!.evict(key), true); + expect(imageCache.evict(key), true); // Force us to the end of the frame. - SchedulerBinding.instance!.scheduleFrame(); - await SchedulerBinding.instance!.endOfFrame; + SchedulerBinding.instance.scheduleFrame(); + await SchedulerBinding.instance.endOfFrame; // -1 _CachedImage // -1 ImageStreamCompleter @@ -551,7 +551,7 @@ void main() { final TestImageStreamCompleter completer = TestImageStreamCompleter(); completer.addListener(listener); - imageCache!.putIfAbsent(key, () => completer); + imageCache.putIfAbsent(key, () => completer); expect(testImage.debugGetOpenHandleStackTraces()!.length, 1); @@ -561,11 +561,11 @@ void main() { // Just our imageInfo and the completer. expect(testImage.debugGetOpenHandleStackTraces()!.length, 2); - expect(imageCache!.evict(key), true); + expect(imageCache.evict(key), true); // Force us to the end of the frame. - SchedulerBinding.instance!.scheduleFrame(); - await SchedulerBinding.instance!.endOfFrame; + SchedulerBinding.instance.scheduleFrame(); + await SchedulerBinding.instance.endOfFrame; // Live image still around since there's still a listener, and the listener // should be holding a handle. diff --git a/packages/flutter/test/painting/image_provider_and_image_cache_test.dart b/packages/flutter/test/painting/image_provider_and_image_cache_test.dart index 785a8ebdaf4..fc9ed3059ae 100644 --- a/packages/flutter/test/painting/image_provider_and_image_cache_test.dart +++ b/packages/flutter/test/painting/image_provider_and_image_cache_test.dart @@ -18,7 +18,7 @@ void main() { TestRenderingFlutterBinding(); Future _basicDecoder(Uint8List bytes, {int? cacheWidth, int? cacheHeight, bool? allowUpscaling}) { - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); } FlutterExceptionHandler? oldError; @@ -28,12 +28,12 @@ void main() { tearDown(() { FlutterError.onError = oldError; - PaintingBinding.instance!.imageCache!.clear(); - PaintingBinding.instance!.imageCache!.clearLiveImages(); + PaintingBinding.instance.imageCache.clear(); + PaintingBinding.instance.imageCache.clearLiveImages(); }); tearDown(() { - imageCache!.clear(); + imageCache.clear(); }); test('AssetImageProvider - evicts on failure to load', () async { @@ -44,18 +44,18 @@ void main() { const ImageProvider provider = ExactAssetImage('does-not-exist'); final Object key = await provider.obtainKey(ImageConfiguration.empty); - expect(imageCache!.statusForKey(provider).untracked, true); - expect(imageCache!.pendingImageCount, 0); + expect(imageCache.statusForKey(provider).untracked, true); + expect(imageCache.pendingImageCount, 0); provider.resolve(ImageConfiguration.empty); - expect(imageCache!.statusForKey(key).pending, true); - expect(imageCache!.pendingImageCount, 1); + expect(imageCache.statusForKey(key).pending, true); + expect(imageCache.pendingImageCount, 1); await error.future; - expect(imageCache!.statusForKey(provider).untracked, true); - expect(imageCache!.pendingImageCount, 0); + expect(imageCache.statusForKey(provider).untracked, true); + expect(imageCache.pendingImageCount, 0); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/56314 test('ImageProvider can evict images', () async { @@ -66,9 +66,9 @@ void main() { stream.addListener(ImageStreamListener((ImageInfo info, bool syncCall) => completer.complete())); await completer.future; - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); expect(await MemoryImage(bytes).evict(), true); - expect(imageCache!.currentSize, 0); + expect(imageCache.currentSize, 0); }); test('ImageProvider.evict respects the provided ImageCache', () async { @@ -90,10 +90,10 @@ void main() { await Future.wait(>[completer.future, cacheCompleter.future]); expect(otherCache.currentSize, 1); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); expect(await imageProvider.evict(cache: otherCache), true); expect(otherCache.currentSize, 0); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); }); test('ImageProvider errors can always be caught', () async { diff --git a/packages/flutter/test/painting/image_provider_network_image_test.dart b/packages/flutter/test/painting/image_provider_network_image_test.dart index 8c3c64b660f..84ec1039daf 100644 --- a/packages/flutter/test/painting/image_provider_network_image_test.dart +++ b/packages/flutter/test/painting/image_provider_network_image_test.dart @@ -19,7 +19,7 @@ void main() { TestRenderingFlutterBinding(); Future _basicDecoder(Uint8List bytes, {int? cacheWidth, int? cacheHeight, bool? allowUpscaling}) { - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling ?? false); } late _FakeHttpClient httpClient; @@ -31,8 +31,8 @@ void main() { tearDown(() { debugNetworkImageHttpClientProvider = null; - PaintingBinding.instance!.imageCache!.clear(); - PaintingBinding.instance!.imageCache!.clearLiveImages(); + PaintingBinding.instance.imageCache.clear(); + PaintingBinding.instance.imageCache.clearLiveImages(); }); test('Expect thrown exception with statusCode - evicts from cache and drains', () async { @@ -44,13 +44,13 @@ void main() { final Completer caughtError = Completer(); final ImageProvider imageProvider = NetworkImage(nonconst(requestUrl)); - expect(imageCache!.pendingImageCount, 0); - expect(imageCache!.statusForKey(imageProvider).untracked, true); + expect(imageCache.pendingImageCount, 0); + expect(imageCache.statusForKey(imageProvider).untracked, true); final ImageStream result = imageProvider.resolve(ImageConfiguration.empty); - expect(imageCache!.pendingImageCount, 1); - expect(imageCache!.statusForKey(imageProvider).pending, true); + expect(imageCache.pendingImageCount, 1); + expect(imageCache.statusForKey(imageProvider).pending, true); result.addListener(ImageStreamListener((ImageInfo info, bool syncCall) { }, onError: (dynamic error, StackTrace? stackTrace) { @@ -59,8 +59,8 @@ void main() { final dynamic err = await caughtError.future; - expect(imageCache!.pendingImageCount, 0); - expect(imageCache!.statusForKey(imageProvider).untracked, true); + expect(imageCache.pendingImageCount, 0); + expect(imageCache.statusForKey(imageProvider).untracked, true); expect( err, @@ -163,13 +163,13 @@ void main() { debugNetworkImageHttpClientProvider = () => mockHttpClient; final ImageProvider imageProvider = NetworkImage(nonconst('testing.url')); - expect(imageCache!.pendingImageCount, 0); - expect(imageCache!.statusForKey(imageProvider).untracked, true); + expect(imageCache.pendingImageCount, 0); + expect(imageCache.statusForKey(imageProvider).untracked, true); final ImageStream result = imageProvider.resolve(ImageConfiguration.empty); - expect(imageCache!.pendingImageCount, 1); - expect(imageCache!.statusForKey(imageProvider).pending, true); + expect(imageCache.pendingImageCount, 1); + expect(imageCache.statusForKey(imageProvider).pending, true); final Completer caughtError = Completer(); result.addListener(ImageStreamListener( (ImageInfo info, bool syncCall) {}, @@ -182,9 +182,9 @@ void main() { expect(err, isA()); - expect(imageCache!.pendingImageCount, 0); - expect(imageCache!.statusForKey(imageProvider).untracked, true); - expect(imageCache!.containsKey(result), isFalse); + expect(imageCache.pendingImageCount, 0); + expect(imageCache.statusForKey(imageProvider).untracked, true); + expect(imageCache.containsKey(result), isFalse); debugNetworkImageHttpClientProvider = null; }, skip: isBrowser); // Browser does not resolve images this way. diff --git a/packages/flutter/test/painting/image_provider_resize_image_test.dart b/packages/flutter/test/painting/image_provider_resize_image_test.dart index ea1a413a305..1fab62b8fd0 100644 --- a/packages/flutter/test/painting/image_provider_resize_image_test.dart +++ b/packages/flutter/test/painting/image_provider_resize_image_test.dart @@ -16,8 +16,8 @@ void main() { TestRenderingFlutterBinding(); tearDown(() { - PaintingBinding.instance!.imageCache!.clear(); - PaintingBinding.instance!.imageCache!.clearLiveImages(); + PaintingBinding.instance.imageCache.clear(); + PaintingBinding.instance.imageCache.clearLiveImages(); }); test('ResizeImage resizes to the correct dimensions (up)', () async { @@ -103,7 +103,7 @@ void main() { expect(cacheWidth, 123); expect(cacheHeight, 321); expect(allowUpscaling, false); - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); } resizeImage.load(await resizeImage.obtainKey(ImageConfiguration.empty), decode); diff --git a/packages/flutter/test/painting/image_provider_test.dart b/packages/flutter/test/painting/image_provider_test.dart index 28b317185ba..94ee97142f1 100644 --- a/packages/flutter/test/painting/image_provider_test.dart +++ b/packages/flutter/test/painting/image_provider_test.dart @@ -27,8 +27,8 @@ void main() { tearDown(() { FlutterError.onError = oldError; - PaintingBinding.instance!.imageCache!.clear(); - PaintingBinding.instance!.imageCache!.clearLiveImages(); + PaintingBinding.instance.imageCache.clear(); + PaintingBinding.instance.imageCache.clearLiveImages(); }); test('obtainKey errors will be caught', () async { @@ -115,17 +115,17 @@ void main() { final File file = fs.file('/empty.png')..createSync(recursive: true); final FileImage provider = FileImage(file); - expect(imageCache!.statusForKey(provider).untracked, true); - expect(imageCache!.pendingImageCount, 0); + expect(imageCache.statusForKey(provider).untracked, true); + expect(imageCache.pendingImageCount, 0); provider.resolve(ImageConfiguration.empty); - expect(imageCache!.statusForKey(provider).pending, true); - expect(imageCache!.pendingImageCount, 1); + expect(imageCache.statusForKey(provider).pending, true); + expect(imageCache.pendingImageCount, 1); expect(await error.future, isStateError); - expect(imageCache!.statusForKey(provider).untracked, true); - expect(imageCache!.pendingImageCount, 0); + expect(imageCache.statusForKey(provider).untracked, true); + expect(imageCache.pendingImageCount, 0); }); test('File image with empty file throws expected error (load)', () async { diff --git a/packages/flutter/test/painting/image_stream_test.dart b/packages/flutter/test/painting/image_stream_test.dart index 274fd32a001..0e3bf8b4b27 100644 --- a/packages/flutter/test/painting/image_stream_test.dart +++ b/packages/flutter/test/painting/image_stream_test.dart @@ -738,7 +738,7 @@ void main() { expect(lastListenerDropped, false); final ImageStreamCompleterHandle handle = imageStream.keepAlive(); expect(lastListenerDropped, false); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Only passive listeners'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Only passive listeners'); codecCompleter.complete(mockCodec); await tester.idle(); @@ -748,7 +748,7 @@ void main() { final FakeFrameInfo frame1 = FakeFrameInfo(Duration.zero, image20x10); mockCodec.completeNextFrame(frame1); await tester.idle(); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Only passive listeners'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Only passive listeners'); await tester.pump(); expect(onImageCount, 0); @@ -757,7 +757,7 @@ void main() { final FakeFrameInfo frame2 = FakeFrameInfo(Duration.zero, image10x10); mockCodec.completeNextFrame(frame2); await tester.idle(); - expect(SchedulerBinding.instance!.transientCallbackCount, 1); + expect(SchedulerBinding.instance.transientCallbackCount, 1); await tester.pump(); expect(onImageCount, 1); @@ -767,16 +767,16 @@ void main() { mockCodec.completeNextFrame(frame1); await tester.idle(); - expect(SchedulerBinding.instance!.transientCallbackCount, 1); + expect(SchedulerBinding.instance.transientCallbackCount, 1); await tester.pump(); expect(onImageCount, 1); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Only passive listeners'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Only passive listeners'); mockCodec.completeNextFrame(frame2); await tester.idle(); - SchedulerBinding.instance!.debugAssertNoTransientCallbacks('Only passive listeners'); + SchedulerBinding.instance.debugAssertNoTransientCallbacks('Only passive listeners'); await tester.pump(); expect(onImageCount, 1); diff --git a/packages/flutter/test/painting/system_fonts_test.dart b/packages/flutter/test/painting/system_fonts_test.dart index a6c36919487..34034eb2968 100644 --- a/packages/flutter/test/painting/system_fonts_test.dart +++ b/packages/flutter/test/painting/system_fonts_test.dart @@ -18,7 +18,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -36,7 +36,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -57,7 +57,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -81,7 +81,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -109,7 +109,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -139,7 +139,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -169,7 +169,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -195,7 +195,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, @@ -239,7 +239,7 @@ void main() { const Map data = { 'type': 'fontsChange', }; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/system', SystemChannels.system.codec.encodeMessage(data), (ByteData? data) { }, diff --git a/packages/flutter/test/painting/text_span_test.dart b/packages/flutter/test/painting/text_span_test.dart index c43fd8da562..75cb91d0d8e 100644 --- a/packages/flutter/test/painting/text_span_test.dart +++ b/packages/flutter/test/painting/text_span_test.dart @@ -309,13 +309,13 @@ void main() { addTearDown(gesture.removePointer); await gesture.moveTo(tester.getCenter(find.byType(RichText)) - const Offset(40, 0)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await gesture.moveTo(tester.getCenter(find.byType(RichText))); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); await gesture.moveTo(tester.getCenter(find.byType(RichText)) + const Offset(40, 0)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('handles onEnter and onExit', (WidgetTester tester) async { diff --git a/packages/flutter/test/rendering/editable_gesture_test.dart b/packages/flutter/test/rendering/editable_gesture_test.dart index 3929f1fa289..a29ae0fb4be 100644 --- a/packages/flutter/test/rendering/editable_gesture_test.dart +++ b/packages/flutter/test/rendering/editable_gesture_test.dart @@ -37,11 +37,11 @@ void main() { editable.layout(BoxConstraints.loose(const Size(1000.0, 1000.0))); final PipelineOwner owner = PipelineOwner(onNeedVisualUpdate: () { }); - final _PointerRouterSpy spy = GestureBinding.instance!.pointerRouter as _PointerRouterSpy; + final _PointerRouterSpy spy = GestureBinding.instance.pointerRouter as _PointerRouterSpy; editable.attach(owner); // This should register pointer into GestureBinding.instance.pointerRouter. editable.handleEvent(const PointerDownEvent(), BoxHitTestEntry(editable, const Offset(10,10))); - GestureBinding.instance!.pointerRouter.route(const PointerDownEvent()); + GestureBinding.instance.pointerRouter.route(const PointerDownEvent()); expect(spy.routeCount, greaterThan(0)); editable.detach(); expect(spy.routeCount, 0); diff --git a/packages/flutter/test/rendering/mouse_tracker_test.dart b/packages/flutter/test/rendering/mouse_tracker_test.dart index 8b2dec51d41..597ed9b60c4 100644 --- a/packages/flutter/test/rendering/mouse_tracker_test.dart +++ b/packages/flutter/test/rendering/mouse_tracker_test.dart @@ -11,7 +11,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'mouse_tracker_test_utils.dart'; -MouseTracker get _mouseTracker => RendererBinding.instance!.mouseTracker; +MouseTracker get _mouseTracker => RendererBinding.instance.mouseTracker; typedef SimpleAnnotationFinder = Iterable Function(Offset offset); diff --git a/packages/flutter/test/rendering/view_chrome_style_test.dart b/packages/flutter/test/rendering/view_chrome_style_test.dart index e5a751f76f6..5218e82f534 100644 --- a/packages/flutter/test/rendering/view_chrome_style_test.dart +++ b/packages/flutter/test/rendering/view_chrome_style_test.dart @@ -17,7 +17,7 @@ void main() { const double devicePixelRatio = 2.0; void setupTestDevice() { - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); const FakeWindowPadding padding = FakeWindowPadding( top: statusBarHeight * devicePixelRatio, bottom: navigationBarHeight * devicePixelRatio, diff --git a/packages/flutter/test/scheduler/scheduler_test.dart b/packages/flutter/test/scheduler/scheduler_test.dart index ec1b9054531..d65c9707efa 100644 --- a/packages/flutter/test/scheduler/scheduler_test.dart +++ b/packages/flutter/test/scheduler/scheduler_test.dart @@ -164,7 +164,7 @@ void main() { FlutterError.onError = (FlutterErrorDetails details) { errorCaught = details; }; - SchedulerBinding.instance!.addTimingsCallback((List timings) { + SchedulerBinding.instance.addTimingsCallback((List timings) { throw Exception('Test'); }); window.onReportTimings!([]); diff --git a/packages/flutter/test/scheduler/scheduler_tester.dart b/packages/flutter/test/scheduler/scheduler_tester.dart index da8eb8963d5..c7db6250b14 100644 --- a/packages/flutter/test/scheduler/scheduler_tester.dart +++ b/packages/flutter/test/scheduler/scheduler_tester.dart @@ -10,6 +10,6 @@ class Future { } // so that people can't import us and dart:async void tick(Duration duration) { // We don't bother running microtasks between these two calls // because we don't use Futures in these tests and so don't care. - SchedulerBinding.instance!.handleBeginFrame(duration); - SchedulerBinding.instance!.handleDrawFrame(); + SchedulerBinding.instance.handleBeginFrame(duration); + SchedulerBinding.instance.handleDrawFrame(); } diff --git a/packages/flutter/test/scheduler/ticker_test.dart b/packages/flutter/test/scheduler/ticker_test.dart index 6c8dedc5bca..eff53329291 100644 --- a/packages/flutter/test/scheduler/ticker_test.dart +++ b/packages/flutter/test/scheduler/ticker_test.dart @@ -149,7 +149,7 @@ void main() { expect(tickCount, equals(0)); final ByteData? message = const StringCodec().encodeMessage('AppLifecycleState.paused'); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); expect(ticker.isTicking, isFalse); expect(ticker.isActive, isTrue); @@ -158,7 +158,7 @@ void main() { testWidgets('Ticker can be created before application unpauses', (WidgetTester tester) async { final ByteData? pausedMessage = const StringCodec().encodeMessage('AppLifecycleState.paused'); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', pausedMessage, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', pausedMessage, (_) { }); int tickCount = 0; void handleTick(Duration duration) { @@ -177,7 +177,7 @@ void main() { expect(ticker.isTicking, isFalse); final ByteData? resumedMessage = const StringCodec().encodeMessage('AppLifecycleState.resumed'); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', resumedMessage, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', resumedMessage, (_) { }); await tester.pump(const Duration(milliseconds: 10)); diff --git a/packages/flutter/test/scheduler/time_dilation_test.dart b/packages/flutter/test/scheduler/time_dilation_test.dart new file mode 100644 index 00000000000..d4c134b1a4c --- /dev/null +++ b/packages/flutter/test/scheduler/time_dilation_test.dart @@ -0,0 +1,16 @@ +// 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/scheduler.dart'; +import 'package:flutter_test/flutter_test.dart' show test, expect; + +// This file should not use testWidgets, and should not instantiate the binding. + +void main() { + test('timeDilation can be set without a binding', () { + expect(timeDilation, 1.0); + timeDilation = 2.0; + expect(timeDilation, 2.0); + }); +} diff --git a/packages/flutter/test/services/default_binary_messenger_test.dart b/packages/flutter/test/services/default_binary_messenger_test.dart index 9d26f60d998..431af98be24 100644 --- a/packages/flutter/test/services/default_binary_messenger_test.dart +++ b/packages/flutter/test/services/default_binary_messenger_test.dart @@ -25,7 +25,7 @@ void main() { const String channel = 'foo'; final ByteData bar = _makeByteData('bar'); final Completer done = Completer(); - ServicesBinding.instance!.channelBuffers.push( + ServicesBinding.instance.channelBuffers.push( channel, bar, (ByteData? message) async { @@ -36,7 +36,7 @@ void main() { ); expect(countInbound, equals(0)); expect(countOutbound, equals(0)); - ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler( + ServicesBinding.instance.defaultBinaryMessenger.setMessageHandler( channel, (ByteData? message) async { expect(message, bar); diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart index dec83b3bf0c..4038c987050 100644 --- a/packages/flutter/test/services/fake_platform_views.dart +++ b/packages/flutter/test/services/fake_platform_views.dart @@ -150,7 +150,7 @@ class FakeAndroidPlatformViewsController { void invokeViewFocused(int viewId) { final MethodCodec codec = SystemChannels.platform_views.codec; final ByteData data = codec.encodeMethodCall(MethodCall('viewFocused', viewId)); - ServicesBinding.instance!.defaultBinaryMessenger + ServicesBinding.instance.defaultBinaryMessenger .handlePlatformMessage(SystemChannels.platform_views.name, data, (ByteData? data) {}); } diff --git a/packages/flutter/test/services/lifecycle_test.dart b/packages/flutter/test/services/lifecycle_test.dart index becb8a1d440..27eb3463441 100644 --- a/packages/flutter/test/services/lifecycle_test.dart +++ b/packages/flutter/test/services/lifecycle_test.dart @@ -9,7 +9,7 @@ void main() { testWidgets('initialLifecycleState is used to init state paused', (WidgetTester tester) async { // The lifecycleState is null initially in tests as there is no // initialLifecycleState. - expect(ServicesBinding.instance!.lifecycleState, equals(null)); + expect(ServicesBinding.instance.lifecycleState, equals(null)); // Mock the Window to provide paused as the AppLifecycleState final TestWidgetsFlutterBinding binding = tester.binding; // Use paused as the initial state. @@ -18,6 +18,6 @@ void main() { // The lifecycleState should now be the state we passed above, // even though no lifecycle event was fired from the platform. - expect(ServicesBinding.instance!.lifecycleState.toString(), equals('AppLifecycleState.paused')); + expect(ServicesBinding.instance.lifecycleState.toString(), equals('AppLifecycleState.paused')); }); } diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 07dc8672ee6..8b5a8892b16 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -390,7 +390,7 @@ void main() { isDown: false, )..['metaState'] = 0; // Dispatch the modified data. - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data2), (ByteData? data) {}, @@ -410,7 +410,7 @@ void main() { ); data['metaState'] = (data['metaState'] as int) | RawKeyEventDataWeb.modifierShift; // Dispatch the modified data. - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data3), (ByteData? data) {}, @@ -431,7 +431,7 @@ void main() { isDown: false, )..['metaState'] = 0; // Dispatch the modified data. - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data4), (ByteData? data) {}, @@ -535,7 +535,7 @@ void main() { RawKeyEventDataIos.modifierCommand | RawKeyEventDataIos.modifierControl; // dispatch the modified data. - await ServicesBinding.instance?.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -1550,7 +1550,7 @@ void main() { final List events = []; // Simulate raw events because VK_PROCESSKEY does not exist in the key mapping. Future simulateKeyEventMessage(String type, int keyCode, int scanCode) { - return ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + return ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage({ 'type': type, diff --git a/packages/flutter/test/services/restoration.dart b/packages/flutter/test/services/restoration.dart index 0ae914da4ae..25f106866e1 100644 --- a/packages/flutter/test/services/restoration.dart +++ b/packages/flutter/test/services/restoration.dart @@ -59,7 +59,7 @@ class MockRestorationManager extends TestRestorationManager { set rootBucket(Future value) { _rootBucket = value; _isRestoring = true; - ServicesBinding.instance!.addPostFrameCallback((Duration _) { + ServicesBinding.instance.addPostFrameCallback((Duration _) { _isRestoring = false; }); notifyListeners(); diff --git a/packages/flutter/test/services/restoration_test.dart b/packages/flutter/test/services/restoration_test.dart index cc132308c3a..ddbd6481586 100644 --- a/packages/flutter/test/services/restoration_test.dart +++ b/packages/flutter/test/services/restoration_test.dart @@ -212,7 +212,7 @@ void main() { callsToEngine.clear(); // Schedule a frame. - SchedulerBinding.instance!.ensureVisualUpdate(); + SchedulerBinding.instance.ensureVisualUpdate(); rootBucket!.write('foo', 1); // flushData is no-op because frame is scheduled. manager.flushData(); @@ -305,7 +305,7 @@ void main() { } Future _pushDataFromEngine(Map data) async { - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/restoration', const StandardMethodCodec().encodeMethodCall(MethodCall('push', data)), (_) { }, diff --git a/packages/flutter/test/services/text_input_test.dart b/packages/flutter/test/services/text_input_test.dart index ca5b626c613..f9f2d3445b1 100644 --- a/packages/flutter/test/services/text_input_test.dart +++ b/packages/flutter/test/services/text_input_test.dart @@ -203,7 +203,7 @@ void main() { 'args': [1], 'method': 'TextInputClient.onConnectionClosed', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -228,7 +228,7 @@ void main() { ], 'method': 'TextInputClient.performPrivateCommand', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -253,7 +253,7 @@ void main() { ], 'method': 'TextInputClient.performPrivateCommand', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -278,7 +278,7 @@ void main() { ], 'method': 'TextInputClient.performPrivateCommand', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -304,7 +304,7 @@ void main() { ], 'method': 'TextInputClient.performPrivateCommand', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -330,7 +330,7 @@ void main() { ], 'method': 'TextInputClient.performPrivateCommand', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, @@ -353,7 +353,7 @@ void main() { 'args': [1, 0, 1], 'method': 'TextInputClient.showAutocorrectionPromptRect', }); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( 'flutter/textinput', messageBytes, (ByteData? _) {}, diff --git a/packages/flutter/test/widgets/actions_test.dart b/packages/flutter/test/widgets/actions_test.dart index b9b70372d1d..d17cb56968e 100644 --- a/packages/flutter/test/widgets/actions_test.dart +++ b/packages/flutter/test/widgets/actions_test.dart @@ -477,7 +477,7 @@ void main() { addTearDown(gesture.removePointer); await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); // Test default await tester.pumpWidget( @@ -491,7 +491,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); }); testWidgets('Actions.invoke returns the value of Action.invoke', (WidgetTester tester) async { final GlobalKey containerKey = GlobalKey(); diff --git a/packages/flutter/test/widgets/annotated_region_test.dart b/packages/flutter/test/widgets/annotated_region_test.dart index 133949c1bb5..00b0ab28864 100644 --- a/packages/flutter/test/widgets/annotated_region_test.dart +++ b/packages/flutter/test/widgets/annotated_region_test.dart @@ -30,12 +30,12 @@ void main() { ), ), ); - int? result = RendererBinding.instance!.renderView.debugLayer!.find(Offset( + int? result = RendererBinding.instance.renderView.debugLayer!.find(Offset( 10.0 * window.devicePixelRatio, 10.0 * window.devicePixelRatio, )); expect(result, null); - result = RendererBinding.instance!.renderView.debugLayer!.find(Offset( + result = RendererBinding.instance.renderView.debugLayer!.find(Offset( 50.0 * window.devicePixelRatio, 50.0 * window.devicePixelRatio, )); diff --git a/packages/flutter/test/widgets/app_test.dart b/packages/flutter/test/widgets/app_test.dart index d0c6778f1af..f88cb0bd9fb 100644 --- a/packages/flutter/test/widgets/app_test.dart +++ b/packages/flutter/test/widgets/app_test.dart @@ -295,7 +295,7 @@ void main() { // Simulate android back button intent. final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); }); diff --git a/packages/flutter/test/widgets/binding_attach_root_widget_test.dart b/packages/flutter/test/widgets/binding_attach_root_widget_test.dart index 03b5b7ed238..85fb43096eb 100644 --- a/packages/flutter/test/widgets/binding_attach_root_widget_test.dart +++ b/packages/flutter/test/widgets/binding_attach_root_widget_test.dart @@ -10,12 +10,12 @@ import 'package:flutter_test/flutter_test.dart'; void main() { test('attachRootWidget will schedule a frame', () async { final WidgetsFlutterBinding binding = WidgetsFlutterBinding.ensureInitialized() as WidgetsFlutterBinding; - expect(SchedulerBinding.instance!.hasScheduledFrame, isFalse); + expect(SchedulerBinding.instance.hasScheduledFrame, isFalse); // Framework starts with detached statue. Sends resumed signal to enable frame. final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed')!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); binding.attachRootWidget(const Placeholder()); - expect(SchedulerBinding.instance!.hasScheduledFrame, isTrue); + expect(SchedulerBinding.instance.hasScheduledFrame, isTrue); }); } diff --git a/packages/flutter/test/widgets/binding_cannot_schedule_frame_test.dart b/packages/flutter/test/widgets/binding_cannot_schedule_frame_test.dart index bb48c74380b..2d19139bd0e 100644 --- a/packages/flutter/test/widgets/binding_cannot_schedule_frame_test.dart +++ b/packages/flutter/test/widgets/binding_cannot_schedule_frame_test.dart @@ -10,22 +10,22 @@ import 'package:flutter_test/flutter_test.dart'; void main() { test('Can only schedule frames after widget binding attaches the root widget', () async { final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized(); - expect(SchedulerBinding.instance!.framesEnabled, isFalse); - expect(SchedulerBinding.instance!.hasScheduledFrame, isFalse); + expect(SchedulerBinding.instance.framesEnabled, isFalse); + expect(SchedulerBinding.instance.hasScheduledFrame, isFalse); // Sends a message to notify that the engine is ready to accept frames. final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed')!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); // Enables the semantics should not schedule any frames if the root widget // has not been attached. binding.setSemanticsEnabled(true); - expect(SchedulerBinding.instance!.framesEnabled, isFalse); - expect(SchedulerBinding.instance!.hasScheduledFrame, isFalse); + expect(SchedulerBinding.instance.framesEnabled, isFalse); + expect(SchedulerBinding.instance.hasScheduledFrame, isFalse); // The widget binding should be ready to produce frames after it attaches // the root widget. binding.attachRootWidget(const Placeholder()); - expect(SchedulerBinding.instance!.framesEnabled, isTrue); - expect(SchedulerBinding.instance!.hasScheduledFrame, isTrue); + expect(SchedulerBinding.instance.framesEnabled, isTrue); + expect(SchedulerBinding.instance.hasScheduledFrame, isTrue); }); } diff --git a/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart b/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart index 278c5e5a050..dc7208c5dd1 100644 --- a/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart +++ b/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart @@ -14,7 +14,7 @@ const String _loading = 'Loading...'; void main() { testWidgets('deferFirstFrame/allowFirstFrame stops sending frames to engine', (WidgetTester tester) async { - expect(RendererBinding.instance!.sendFramesToEngine, isTrue); + expect(RendererBinding.instance.sendFramesToEngine, isTrue); final Completer completer = Completer(); await tester.pumpWidget( @@ -30,28 +30,28 @@ void main() { expect(find.text(_loading), findsOneWidget); expect(find.text(_actualContent), findsNothing); - expect(RendererBinding.instance!.sendFramesToEngine, isFalse); + expect(RendererBinding.instance.sendFramesToEngine, isFalse); await tester.pump(); expect(find.text(_loading), findsOneWidget); expect(find.text(_actualContent), findsNothing); - expect(RendererBinding.instance!.sendFramesToEngine, isFalse); + expect(RendererBinding.instance.sendFramesToEngine, isFalse); expect(state.doneLoading, isFalse); // Complete the future to start sending frames. completer.complete(); await tester.idle(); expect(state.doneLoading, isTrue); - expect(RendererBinding.instance!.sendFramesToEngine, isTrue); + expect(RendererBinding.instance.sendFramesToEngine, isTrue); await tester.pump(); expect(find.text(_loading), findsNothing); expect(find.text(_actualContent), findsOneWidget); - expect(RendererBinding.instance!.sendFramesToEngine, isTrue); + expect(RendererBinding.instance.sendFramesToEngine, isTrue); }); testWidgets('Two widgets can defer frames', (WidgetTester tester) async { - expect(RendererBinding.instance!.sendFramesToEngine, isTrue); + expect(RendererBinding.instance.sendFramesToEngine, isTrue); final Completer completer1 = Completer(); final Completer completer2 = Completer(); @@ -74,7 +74,7 @@ void main() { ); expect(find.text(_loading), findsNWidgets(2)); expect(find.text(_actualContent), findsNothing); - expect(RendererBinding.instance!.sendFramesToEngine, isFalse); + expect(RendererBinding.instance.sendFramesToEngine, isFalse); completer1.complete(); completer2.complete(); @@ -83,7 +83,7 @@ void main() { await tester.pump(); expect(find.text(_loading), findsNothing); expect(find.text(_actualContent), findsNWidgets(2)); - expect(RendererBinding.instance!.sendFramesToEngine, isTrue); + expect(RendererBinding.instance.sendFramesToEngine, isTrue); }); } @@ -102,11 +102,11 @@ class _DeferringWidgetState extends State<_DeferringWidget> { @override void initState() { super.initState(); - RendererBinding.instance!.deferFirstFrame(); + RendererBinding.instance.deferFirstFrame(); widget.loader.then((_) { setState(() { doneLoading = true; - RendererBinding.instance!.allowFirstFrame(); + RendererBinding.instance.allowFirstFrame(); }); }); } diff --git a/packages/flutter/test/widgets/binding_frame_scheduling_test.dart b/packages/flutter/test/widgets/binding_frame_scheduling_test.dart index 9d34957feaa..f4a1879b24b 100644 --- a/packages/flutter/test/widgets/binding_frame_scheduling_test.dart +++ b/packages/flutter/test/widgets/binding_frame_scheduling_test.dart @@ -4,6 +4,7 @@ import 'dart:ui' show window; +import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -13,26 +14,26 @@ void main() { // Regression test for https://github.com/flutter/flutter/issues/39494. // Preconditions. - expect(WidgetsBinding.instance, isNull); expect(window.onBeginFrame, isNull); expect(window.onDrawFrame, isNull); // Instantiation does nothing with regards to frame scheduling. - final WidgetsFlutterBinding binding = WidgetsFlutterBinding.ensureInitialized() as WidgetsFlutterBinding; - expect(binding.hasScheduledFrame, isFalse); + expect(WidgetsFlutterBinding.ensureInitialized(), isA()); + expect(SchedulerBinding.instance.hasScheduledFrame, isFalse); expect(window.onBeginFrame, isNull); expect(window.onDrawFrame, isNull); // Framework starts with detached statue. Sends resumed signal to enable frame. final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed')!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); + expect(window.onBeginFrame, isNull); + expect(window.onDrawFrame, isNull); + expect(SchedulerBinding.instance.hasScheduledFrame, isFalse); - // A frame can only be scheduled when there is a root widget. - binding.attachRootWidget(const Placeholder()); - - // Frame callbacks are registered lazily when a frame is scheduled. - binding.scheduleFrame(); + // Frame callbacks are registered lazily (and a frame scheduled) when the root widget is attached. + WidgetsBinding.instance.attachRootWidget(const Placeholder()); expect(window.onBeginFrame, isNotNull); expect(window.onDrawFrame, isNotNull); + expect(SchedulerBinding.instance.hasScheduledFrame, isTrue); }); } diff --git a/packages/flutter/test/widgets/binding_test.dart b/packages/flutter/test/widgets/binding_test.dart index db64af8249b..5f25e90e39e 100644 --- a/packages/flutter/test/widgets/binding_test.dart +++ b/packages/flutter/test/widgets/binding_test.dart @@ -52,17 +52,17 @@ void main() { testWidgets('didHaveMemoryPressure callback', (WidgetTester tester) async { final MemoryPressureObserver observer = MemoryPressureObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); final ByteData message = const JSONMessageCodec().encodeMessage({'type': 'memoryPressure'})!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/system', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/system', message, (_) { }); expect(observer.sawMemoryPressure, true); - WidgetsBinding.instance!.removeObserver(observer); + WidgetsBinding.instance.removeObserver(observer); }); testWidgets('handleLifecycleStateChanged callback', (WidgetTester tester) async { - final BinaryMessenger defaultBinaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger; + final BinaryMessenger defaultBinaryMessenger = ServicesBinding.instance.defaultBinaryMessenger; final AppLifecycleStateObserver observer = AppLifecycleStateObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); ByteData message = const StringCodec().encodeMessage('AppLifecycleState.paused')!; await defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); @@ -83,19 +83,19 @@ void main() { testWidgets('didPushRoute callback', (WidgetTester tester) async { final PushRouteObserver observer = PushRouteObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); const String testRouteName = 'testRouteName'; final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('pushRoute', testRouteName)); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); expect(observer.pushedRoute, testRouteName); - WidgetsBinding.instance!.removeObserver(observer); + WidgetsBinding.instance.removeObserver(observer); }); testWidgets('didPushRouteInformation calls didPushRoute by default', (WidgetTester tester) async { final PushRouteObserver observer = PushRouteObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); const Map testRouteInformation = { 'location': 'testRouteName', @@ -105,14 +105,14 @@ void main() { final ByteData message = const JSONMethodCodec().encodeMethodCall( const MethodCall('pushRouteInformation', testRouteInformation), ); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); expect(observer.pushedRoute, 'testRouteName'); - WidgetsBinding.instance!.removeObserver(observer); + WidgetsBinding.instance.removeObserver(observer); }); testWidgets('didPushRouteInformation callback', (WidgetTester tester) async { final PushRouteInformationObserver observer = PushRouteInformationObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); const Map testRouteInformation = { 'location': 'testRouteName', @@ -121,16 +121,16 @@ void main() { final ByteData message = const JSONMethodCodec().encodeMethodCall( const MethodCall('pushRouteInformation', testRouteInformation), ); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); expect(observer.pushedRouteInformation.location, 'testRouteName'); expect(observer.pushedRouteInformation.state, 'state'); - WidgetsBinding.instance!.removeObserver(observer); + WidgetsBinding.instance.removeObserver(observer); }); testWidgets('didPushRouteInformation callback with null state', (WidgetTester tester) async { final PushRouteInformationObserver observer = PushRouteInformationObserver(); - WidgetsBinding.instance!.addObserver(observer); + WidgetsBinding.instance.addObserver(observer); const Map testRouteInformation = { 'location': 'testRouteName', @@ -139,14 +139,14 @@ void main() { final ByteData message = const JSONMethodCodec().encodeMethodCall( const MethodCall('pushRouteInformation', testRouteInformation), ); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); expect(observer.pushedRouteInformation.location, 'testRouteName'); expect(observer.pushedRouteInformation.state, null); - WidgetsBinding.instance!.removeObserver(observer); + WidgetsBinding.instance.removeObserver(observer); }); testWidgets('Application lifecycle affects frame scheduling', (WidgetTester tester) async { - final BinaryMessenger defaultBinaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger; + final BinaryMessenger defaultBinaryMessenger = ServicesBinding.instance.defaultBinaryMessenger; ByteData message; expect(tester.binding.hasScheduledFrame, isFalse); diff --git a/packages/flutter/test/widgets/custom_painter_test.dart b/packages/flutter/test/widgets/custom_painter_test.dart index f6b44333954..c7a7e224766 100644 --- a/packages/flutter/test/widgets/custom_painter_test.dart +++ b/packages/flutter/test/widgets/custom_painter_test.dart @@ -739,7 +739,7 @@ class _DiffTester { )); expect(semanticsTester, hasSemantics(createExpectations(from), ignoreId: true)); - SemanticsNode root = RendererBinding.instance!.renderView.debugSemantics!; + SemanticsNode root = RendererBinding.instance.renderView.debugSemantics!; final Map idAssignments = {}; root.visitChildren((SemanticsNode firstChild) { firstChild.visitChildren((SemanticsNode node) { @@ -757,7 +757,7 @@ class _DiffTester { await tester.pumpAndSettle(); expect(semanticsTester, hasSemantics(createExpectations(to), ignoreId: true)); - root = RendererBinding.instance!.renderView.debugSemantics!; + root = RendererBinding.instance.renderView.debugSemantics!; root.visitChildren((SemanticsNode firstChild) { firstChild.visitChildren((SemanticsNode node) { if (node.key != null && idAssignments[node.key] != null) { diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 2c902edba7f..26af3e32236 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -66,8 +66,9 @@ class MockClipboard { void main() { final MockClipboard mockClipboard = MockClipboard(); - (TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding) - .defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + TestWidgetsFlutterBinding.ensureInitialized() + .defaultBinaryMessenger + .setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); setUp(() async { debugResetSemanticsIdCounter(); @@ -6507,7 +6508,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); // Test default cursor await tester.pumpWidget( @@ -6532,7 +6533,7 @@ void main() { ), ); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); }); testWidgets('Can access characters on editing string', (WidgetTester tester) async { diff --git a/packages/flutter/test/widgets/fade_in_image_test.dart b/packages/flutter/test/widgets/fade_in_image_test.dart index 3b5c429f6cf..93fcf6825cc 100644 --- a/packages/flutter/test/widgets/fade_in_image_test.dart +++ b/packages/flutter/test/widgets/fade_in_image_test.dart @@ -320,7 +320,7 @@ Future main() async { expect(cacheHeight, 30); expect(allowUpscaling, false); called = true; - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); } final ImageProvider resizeImage = image.placeholder; expect(image.placeholder, isA()); @@ -343,7 +343,7 @@ Future main() async { expect(cacheHeight, null); expect(allowUpscaling, false); called = true; - return PaintingBinding.instance!.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight); + return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight); } // image.placeholder should be an instance of MemoryImage instead of ResizeImage final ImageProvider memoryImage = image.placeholder; diff --git a/packages/flutter/test/widgets/fast_reassemble_test.dart b/packages/flutter/test/widgets/fast_reassemble_test.dart index d86d1c9a906..56bedfeb6b2 100644 --- a/packages/flutter/test/widgets/fast_reassemble_test.dart +++ b/packages/flutter/test/widgets/fast_reassemble_test.dart @@ -17,34 +17,34 @@ void main() { expect(Fizz.count, 0); DebugReassembleConfig config = DebugReassembleConfig(widgetName: 'Bar'); - WidgetsBinding.instance!.buildOwner!.reassemble(WidgetsBinding.instance!.renderViewElement!, config); + WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config); expect(Foo.count, 0); expect(Bar.count, 1); expect(Fizz.count, 1); config = DebugReassembleConfig(widgetName: 'Fizz'); - WidgetsBinding.instance!.buildOwner!.reassemble(WidgetsBinding.instance!.renderViewElement!, config); + WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config); expect(Foo.count, 0); expect(Bar.count, 1); expect(Fizz.count, 2); config = DebugReassembleConfig(widgetName: 'NoMatch'); - WidgetsBinding.instance!.buildOwner!.reassemble(WidgetsBinding.instance!.renderViewElement!, config); + WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config); expect(Foo.count, 0); expect(Bar.count, 1); expect(Fizz.count, 2); config = DebugReassembleConfig(); - WidgetsBinding.instance!.buildOwner!.reassemble(WidgetsBinding.instance!.renderViewElement!, config); + WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config); expect(Foo.count, 1); expect(Bar.count, 2); expect(Fizz.count, 3); - WidgetsBinding.instance!.buildOwner!.reassemble(WidgetsBinding.instance!.renderViewElement!, null); + WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, null); expect(Foo.count, 2); expect(Bar.count, 3); diff --git a/packages/flutter/test/widgets/fitted_box_test.dart b/packages/flutter/test/widgets/fitted_box_test.dart index 709123ca41f..1b886a50e7c 100644 --- a/packages/flutter/test/widgets/fitted_box_test.dart +++ b/packages/flutter/test/widgets/fitted_box_test.dart @@ -593,7 +593,7 @@ void main() { List getLayers() { final List layers = []; - Layer? container = RendererBinding.instance!.renderView.debugLayer; + Layer? container = RendererBinding.instance.renderView.debugLayer; while (container is ContainerLayer) { layers.add(container.runtimeType); expect(container.firstChild, same(container.lastChild)); diff --git a/packages/flutter/test/widgets/flow_test.dart b/packages/flutter/test/widgets/flow_test.dart index 9d92e0957d4..87f030ceaf7 100644 --- a/packages/flutter/test/widgets/flow_test.dart +++ b/packages/flutter/test/widgets/flow_test.dart @@ -147,7 +147,7 @@ void main() { ], ), ); - ContainerLayer? layer = RendererBinding.instance!.renderView.debugLayer; + ContainerLayer? layer = RendererBinding.instance.renderView.debugLayer; while (layer != null && layer is! OpacityLayer) layer = layer.firstChild as ContainerLayer?; expect(layer, isA()); diff --git a/packages/flutter/test/widgets/focus_manager_test.dart b/packages/flutter/test/widgets/focus_manager_test.dart index 881c2038146..af20d9117c8 100644 --- a/packages/flutter/test/widgets/focus_manager_test.dart +++ b/packages/flutter/test/widgets/focus_manager_test.dart @@ -955,7 +955,7 @@ void main() { testWidgets('Mouse events change initial focus highlight mode on mobile.', (WidgetTester tester) async { expect(FocusManager.instance.highlightMode, equals(FocusHighlightMode.touch)); - RendererBinding.instance!.initMouseTracker(); // Clear out the mouse state. + RendererBinding.instance.initMouseTracker(); // Clear out the mouse state. final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 0); addTearDown(gesture.removePointer); await gesture.moveTo(Offset.zero); @@ -964,7 +964,7 @@ void main() { testWidgets('Mouse events change initial focus highlight mode on desktop.', (WidgetTester tester) async { expect(FocusManager.instance.highlightMode, equals(FocusHighlightMode.traditional)); - RendererBinding.instance!.initMouseTracker(); // Clear out the mouse state. + RendererBinding.instance.initMouseTracker(); // Clear out the mouse state. final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 0); addTearDown(gesture.removePointer); await gesture.moveTo(Offset.zero); diff --git a/packages/flutter/test/widgets/framework_test.dart b/packages/flutter/test/widgets/framework_test.dart index 5477815041e..6033bfdf3b0 100644 --- a/packages/flutter/test/widgets/framework_test.dart +++ b/packages/flutter/test/widgets/framework_test.dart @@ -1543,11 +1543,11 @@ void main() { }); testWidgets('Can create BuildOwner that does not interfere with pointer router or raw key event handler', (WidgetTester tester) async { - final int pointerRouterCount = GestureBinding.instance!.pointerRouter.debugGlobalRouteCount; + final int pointerRouterCount = GestureBinding.instance.pointerRouter.debugGlobalRouteCount; final RawKeyEventHandler? rawKeyEventHandler = RawKeyboard.instance.keyEventHandler; expect(rawKeyEventHandler, isNotNull); BuildOwner(focusManager: FocusManager()); - expect(GestureBinding.instance!.pointerRouter.debugGlobalRouteCount, pointerRouterCount); + expect(GestureBinding.instance.pointerRouter.debugGlobalRouteCount, pointerRouterCount); expect(RawKeyboard.instance.keyEventHandler, same(rawKeyEventHandler)); }); diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index f195cd3f33f..b1231bc3019 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -21,14 +21,14 @@ void main() { late ui.Image image10x10; setUp(() async { - originalCacheSize = imageCache!.maximumSize; - imageCache!.clear(); - imageCache!.clearLiveImages(); + originalCacheSize = imageCache.maximumSize; + imageCache.clear(); + imageCache.clearLiveImages(); image10x10 = await createTestImage(width: 10, height: 10); }); tearDown(() { - imageCache!.maximumSize = originalCacheSize; + imageCache.maximumSize = originalCacheSize; }); testWidgets('Verify Image resets its RenderImage when changing providers', (WidgetTester tester) async { @@ -1456,14 +1456,14 @@ void main() { }); testWidgets('Same image provider in multiple parts of the tree, no cache room left', (WidgetTester tester) async { - imageCache!.maximumSize = 0; + imageCache.maximumSize = 0; final _TestImageProvider provider1 = _TestImageProvider(); final _TestImageProvider provider2 = _TestImageProvider(); expect(provider1.loadCallCount, 0); expect(provider2.loadCallCount, 0); - expect(imageCache!.liveImageCount, 0); + expect(imageCache.liveImageCount, 0); await tester.pumpWidget(Column( children: [ @@ -1475,13 +1475,13 @@ void main() { ], )); - expect(imageCache!.liveImageCount, 2); - expect(imageCache!.statusForKey(provider1).live, true); - expect(imageCache!.statusForKey(provider1).pending, false); - expect(imageCache!.statusForKey(provider1).keepAlive, false); - expect(imageCache!.statusForKey(provider2).live, true); - expect(imageCache!.statusForKey(provider2).pending, false); - expect(imageCache!.statusForKey(provider2).keepAlive, false); + expect(imageCache.liveImageCount, 2); + expect(imageCache.statusForKey(provider1).live, true); + expect(imageCache.statusForKey(provider1).pending, false); + expect(imageCache.statusForKey(provider1).keepAlive, false); + expect(imageCache.statusForKey(provider2).live, true); + expect(imageCache.statusForKey(provider2).pending, false); + expect(imageCache.statusForKey(provider2).keepAlive, false); expect(provider1.loadCallCount, 1); expect(provider2.loadCallCount, 1); @@ -1492,26 +1492,26 @@ void main() { provider2.complete(image10x10.clone()); await tester.idle(); - expect(imageCache!.liveImageCount, 2); - expect(imageCache!.currentSize, 0); + expect(imageCache.liveImageCount, 2); + expect(imageCache.currentSize, 0); await tester.pumpWidget(Image(image: provider2)); await tester.idle(); - expect(imageCache!.statusForKey(provider1).untracked, true); - expect(imageCache!.statusForKey(provider2).live, true); - expect(imageCache!.statusForKey(provider2).pending, false); - expect(imageCache!.statusForKey(provider2).keepAlive, false); - expect(imageCache!.liveImageCount, 1); + expect(imageCache.statusForKey(provider1).untracked, true); + expect(imageCache.statusForKey(provider2).live, true); + expect(imageCache.statusForKey(provider2).pending, false); + expect(imageCache.statusForKey(provider2).keepAlive, false); + expect(imageCache.liveImageCount, 1); await tester.pumpWidget(const SizedBox()); await tester.idle(); expect(provider1.loadCallCount, 1); expect(provider2.loadCallCount, 1); - expect(imageCache!.liveImageCount, 0); + expect(imageCache.liveImageCount, 0); }); testWidgets('precacheImage does not hold weak ref for more than a frame', (WidgetTester tester) async { - imageCache!.maximumSize = 0; + imageCache.maximumSize = 0; final _TestImageProvider provider = _TestImageProvider(); late Future precache; await tester.pumpWidget( @@ -1526,8 +1526,8 @@ void main() { await precache; // Should have ended up with only a weak ref, not in cache because cache size is 0 - expect(imageCache!.liveImageCount, 1); - expect(imageCache!.containsKey(provider), false); + expect(imageCache.liveImageCount, 1); + expect(imageCache.containsKey(provider), false); final ImageCacheStatus providerLocation = (await provider.obtainCacheStatus(configuration: ImageConfiguration.empty))!; @@ -1544,19 +1544,19 @@ void main() { // Still have live ref because frame has not pumped yet. await tester.pump(); - expect(imageCache!.liveImageCount, 1); + expect(imageCache.liveImageCount, 1); - SchedulerBinding.instance!.scheduleFrame(); + SchedulerBinding.instance.scheduleFrame(); await tester.pump(); // Live ref should be gone - we didn't listen to the stream. - expect(imageCache!.liveImageCount, 0); - expect(imageCache!.currentSize, 0); + expect(imageCache.liveImageCount, 0); + expect(imageCache.currentSize, 0); stream.addListener(listener); expect(isSync, true); // because the stream still has the image. - expect(imageCache!.liveImageCount, 0); - expect(imageCache!.currentSize, 0); + expect(imageCache.liveImageCount, 0); + expect(imageCache.currentSize, 0); expect(provider.loadCallCount, 1); }); @@ -1576,9 +1576,9 @@ void main() { await precache; // Should have ended up in the cache and have a weak reference. - expect(imageCache!.liveImageCount, 1); - expect(imageCache!.currentSize, 1); - expect(imageCache!.containsKey(provider), true); + expect(imageCache.liveImageCount, 1); + expect(imageCache.currentSize, 1); + expect(imageCache.containsKey(provider), true); // Check that a second resolve of the same image is synchronous. expect(provider._lastResolvedConfiguration, isNotNull); @@ -1587,28 +1587,28 @@ void main() { final ImageStreamListener listener = ImageStreamListener((ImageInfo image, bool syncCall) { isSync = syncCall; }); // Should have ended up in the cache and still have a weak reference. - expect(imageCache!.liveImageCount, 1); - expect(imageCache!.currentSize, 1); - expect(imageCache!.containsKey(provider), true); + expect(imageCache.liveImageCount, 1); + expect(imageCache.currentSize, 1); + expect(imageCache.containsKey(provider), true); stream.addListener(listener); expect(isSync, true); - expect(imageCache!.liveImageCount, 1); - expect(imageCache!.currentSize, 1); - expect(imageCache!.containsKey(provider), true); + expect(imageCache.liveImageCount, 1); + expect(imageCache.currentSize, 1); + expect(imageCache.containsKey(provider), true); - SchedulerBinding.instance!.scheduleFrame(); + SchedulerBinding.instance.scheduleFrame(); await tester.pump(); - expect(imageCache!.liveImageCount, 1); - expect(imageCache!.currentSize, 1); - expect(imageCache!.containsKey(provider), true); + expect(imageCache.liveImageCount, 1); + expect(imageCache.currentSize, 1); + expect(imageCache.containsKey(provider), true); stream.removeListener(listener); - expect(imageCache!.liveImageCount, 0); - expect(imageCache!.currentSize, 1); - expect(imageCache!.containsKey(provider), true); + expect(imageCache.liveImageCount, 0); + expect(imageCache.currentSize, 1); + expect(imageCache.containsKey(provider), true); expect(provider.loadCallCount, 1); }); @@ -1629,19 +1629,19 @@ void main() { final List> futures = >[]; await tester.pumpWidget(Builder(builder: (BuildContext context) { futures.add(precacheImage(provider, context)); - imageCache!.evict(provider); + imageCache.evict(provider); futures.add(precacheImage(provider, context)); return const SizedBox.expand(); })); await Future.wait(futures); - expect(imageCache!.statusForKey(provider).keepAlive, true); - expect(imageCache!.statusForKey(provider).live, true); + expect(imageCache.statusForKey(provider).keepAlive, true); + expect(imageCache.statusForKey(provider).live, true); // Schedule a frame to get precacheImage to stop listening. - SchedulerBinding.instance!.scheduleFrame(); + SchedulerBinding.instance.scheduleFrame(); await tester.pump(); - expect(imageCache!.statusForKey(provider).keepAlive, true); - expect(imageCache!.statusForKey(provider).live, false); + expect(imageCache.statusForKey(provider).keepAlive, true); + expect(imageCache.statusForKey(provider).live, false); }); }); @@ -1868,7 +1868,7 @@ void main() { }, skip: kIsWeb); // Web does not care about image handle/disposal. testWidgets('Keeps stream alive when ticker mode is disabled', (WidgetTester tester) async { - imageCache!.maximumSize = 0; + imageCache.maximumSize = 0; final ui.Image image = (await tester.runAsync(() => createTestImage(width: 1, height: 1, cache: false)))!; final _TestImageProvider provider = _TestImageProvider(); provider.complete(image); diff --git a/packages/flutter/test/widgets/independent_widget_layout_test.dart b/packages/flutter/test/widgets/independent_widget_layout_test.dart index 4800e263b8a..dbbf1deda95 100644 --- a/packages/flutter/test/widgets/independent_widget_layout_test.dart +++ b/packages/flutter/test/widgets/independent_widget_layout_test.dart @@ -37,7 +37,7 @@ class ScheduledFrameTrackingBindings extends AutomatedTestWidgetsFlutterBinding class OffscreenRenderView extends RenderView { OffscreenRenderView() : super( configuration: const ViewConfiguration(size: _kTestViewSize), - window: WidgetsBinding.instance!.window, + window: WidgetsBinding.instance.window, ); @override @@ -170,7 +170,7 @@ void main() { testWidgets('RenderObjectToWidgetAdapter.attachToRenderTree does not schedule frame', (WidgetTester tester) async { expect(WidgetsBinding.instance, isA()); - final ScheduledFrameTrackingWindow window = WidgetsBinding.instance!.window as ScheduledFrameTrackingWindow; + final ScheduledFrameTrackingWindow window = WidgetsBinding.instance.window as ScheduledFrameTrackingWindow; window.resetScheduledFrameCount(); expect(window.scheduledFrameCount, isZero); final OffscreenWidgetTree tree = OffscreenWidgetTree(); diff --git a/packages/flutter/test/widgets/media_query_test.dart b/packages/flutter/test/widgets/media_query_test.dart index 7b719491eaf..9a5d23039f3 100644 --- a/packages/flutter/test/widgets/media_query_test.dart +++ b/packages/flutter/test/widgets/media_query_test.dart @@ -100,10 +100,10 @@ void main() { }); testWidgets('MediaQueryData.fromWindow is sane', (WidgetTester tester) async { - final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window); + final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window); expect(data, hasOneLineDescription); expect(data.hashCode, equals(data.copyWith().hashCode)); - expect(data.size, equals(WidgetsBinding.instance!.window.physicalSize / WidgetsBinding.instance!.window.devicePixelRatio)); + expect(data.size, equals(WidgetsBinding.instance.window.physicalSize / WidgetsBinding.instance.window.devicePixelRatio)); expect(data.accessibleNavigation, false); expect(data.invertColors, false); expect(data.disableAnimations, false); @@ -113,7 +113,7 @@ void main() { }); testWidgets('MediaQueryData.copyWith defaults to source', (WidgetTester tester) async { - final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window); + final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window); final MediaQueryData copied = data.copyWith(); expect(copied.size, data.size); expect(copied.devicePixelRatio, data.devicePixelRatio); @@ -142,7 +142,7 @@ void main() { const EdgeInsets customViewInsets = EdgeInsets.all(1.67262); const EdgeInsets customSystemGestureInsets = EdgeInsets.all(1.5556); - final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window); + final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window); final MediaQueryData copied = data.copyWith( size: customSize, devicePixelRatio: customDevicePixelRatio, diff --git a/packages/flutter/test/widgets/modal_barrier_test.dart b/packages/flutter/test/widgets/modal_barrier_test.dart index 050941dd4a3..d004d34ebd3 100644 --- a/packages/flutter/test/widgets/modal_barrier_test.dart +++ b/packages/flutter/test/widgets/modal_barrier_test.dart @@ -425,7 +425,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); } diff --git a/packages/flutter/test/widgets/mouse_region_test.dart b/packages/flutter/test/widgets/mouse_region_test.dart index 6ade4bbef39..bd4eacfe4a4 100644 --- a/packages/flutter/test/widgets/mouse_region_test.dart +++ b/packages/flutter/test/widgets/mouse_region_test.dart @@ -615,13 +615,13 @@ void main() { addTearDown(gesture.removePointer); await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); await gesture.moveTo(const Offset(5, 5)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); await gesture.moveTo(const Offset(100, 100)); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('MouseRegion uses updated callbacks', (WidgetTester tester) async { @@ -1519,7 +1519,7 @@ void main() { await gesture.moveTo(const Offset(5, 5)); expect(logPaints, ['paint']); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); expect(logEnters, ['enter']); logPaints.clear(); logEnters.clear(); @@ -1538,7 +1538,7 @@ void main() { )); expect(logPaints, ['paint']); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(logEnters, isEmpty); logPaints.clear(); logEnters.clear(); @@ -1572,7 +1572,7 @@ void main() { expect(logPaints, ['paint']); expect(logEnters, ['enter']); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); logPaints.clear(); logEnters.clear(); @@ -1593,7 +1593,7 @@ void main() { expect(logPaints, ['paint']); expect(logEnters, isEmpty); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); logPaints.clear(); logEnters.clear(); @@ -1613,7 +1613,7 @@ void main() { )); expect(logPaints, ['paint']); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); expect(logEnters, isEmpty); logPaints.clear(); logEnters.clear(); @@ -1665,7 +1665,7 @@ void main() { expect(logEnters, ['enter']); expect(logExits, isEmpty); expect(logCursors, isNotEmpty); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); logEnters.clear(); logExits.clear(); logCursors.clear(); @@ -1700,7 +1700,7 @@ void main() { expect(logEnters, isEmpty); expect(logExits, isEmpty); expect(logCursors, isEmpty); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); testWidgets("RenderMouseRegion's debugFillProperties when default", (WidgetTester tester) async { diff --git a/packages/flutter/test/widgets/navigator_test.dart b/packages/flutter/test/widgets/navigator_test.dart index ac7346f6a33..e177a3319a6 100644 --- a/packages/flutter/test/widgets/navigator_test.dart +++ b/packages/flutter/test/widgets/navigator_test.dart @@ -2552,7 +2552,7 @@ void main() { List observers = const [], }) { return MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ @@ -2615,7 +2615,7 @@ void main() { await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ @@ -2711,7 +2711,7 @@ void main() { }; await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ diff --git a/packages/flutter/test/widgets/router_test.dart b/packages/flutter/test/widgets/router_test.dart index dee2ab9b697..fdd5ae33256 100644 --- a/packages/flutter/test/widgets/router_test.dart +++ b/packages/flutter/test/widgets/router_test.dart @@ -676,7 +676,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester final ByteData routerMessage = const JSONMethodCodec().encodeMethodCall( const MethodCall('pushRouteInformation', testRouteInformation), ); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', routerMessage, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', routerMessage, (_) { }); await tester.pump(); expect(find.text('testRouteName'), findsOneWidget); expect(find.text('state'), findsOneWidget); @@ -686,7 +686,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester final ByteData message = const JSONMethodCodec().encodeMethodCall( const MethodCall('pushRoute', testRouteName), ); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pump(); expect(find.text('newTestRouteName'), findsOneWidget); }); @@ -721,7 +721,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester // Pop route through the message channel. final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pump(); expect(find.text('popped'), findsOneWidget); }); diff --git a/packages/flutter/test/widgets/routes_test.dart b/packages/flutter/test/widgets/routes_test.dart index 6397fcf84bb..f201157afad 100644 --- a/packages/flutter/test/widgets/routes_test.dart +++ b/packages/flutter/test/widgets/routes_test.dart @@ -1996,7 +1996,7 @@ Widget buildNavigator({ TransitionDelegate? transitionDelegate, }) { return MediaQuery( - data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: Localizations( locale: const Locale('en', 'US'), delegates: const >[ diff --git a/packages/flutter/test/widgets/run_app_async_test.dart b/packages/flutter/test/widgets/run_app_async_test.dart index 662dbf4f9a8..6dc824b7a09 100644 --- a/packages/flutter/test/widgets/run_app_async_test.dart +++ b/packages/flutter/test/widgets/run_app_async_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { setUp(() { WidgetsFlutterBinding.ensureInitialized(); - WidgetsBinding.instance!.resetEpoch(); + WidgetsBinding.instance.resetEpoch(); }); test('WidgetBinding build rendering tree and warm up frame back to back', () { @@ -23,9 +23,9 @@ void main() { ), ); // Rendering tree is not built synchronously. - expect(WidgetsBinding.instance!.renderViewElement, isNull); + expect(WidgetsBinding.instance.renderViewElement, isNull); fakeAsync.flushTimers(); - expect(WidgetsBinding.instance!.renderViewElement, isNotNull); + expect(WidgetsBinding.instance.renderViewElement, isNotNull); }); }); } diff --git a/packages/flutter/test/widgets/scroll_activity_test.dart b/packages/flutter/test/widgets/scroll_activity_test.dart index 07a9805d4d6..9748447506b 100644 --- a/packages/flutter/test/widgets/scroll_activity_test.dart +++ b/packages/flutter/test/widgets/scroll_activity_test.dart @@ -214,13 +214,13 @@ class _Carousel62209State extends State { _pages = widget.pages.toList(); } else { _jumpingToPage = true; - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { if (mounted) { setState(() { _pages = widget.pages.toList(); _currentPage = newPage; _pageController.jumpToPage(_currentPage); - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { _jumpingToPage = false; }); }); diff --git a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart index 954d1e84b41..651f3b04578 100644 --- a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart +++ b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart @@ -18,7 +18,7 @@ void main() { }); tearDown(() { - imageCache?.clear(); + imageCache.clear(); }); T _findPhysics(WidgetTester tester) { @@ -41,19 +41,19 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty); expect(testImageProvider.configuration, ImageConfiguration.empty); expect(stream.completer, isNotNull); expect(stream.completer!.hasListeners, true); - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.currentSize, 0); testImageProvider.complete(); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); }); testWidgets('ScrollAwareImageProvider does not delay if in scrollable that is not scrolling', (WidgetTester tester) async { @@ -76,19 +76,19 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty); expect(testImageProvider.configuration, ImageConfiguration.empty); expect(stream.completer, isNotNull); expect(stream.completer!.hasListeners, true); - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.currentSize, 0); testImageProvider.complete(); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); expect(_findPhysics(tester).velocities, [0]); }); @@ -116,7 +116,7 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); scrollController.animateTo( 100, @@ -141,12 +141,12 @@ void main() { expect(testImageProvider.configuration, ImageConfiguration.empty); expect(stream.completer, isNotNull); expect(stream.completer!.hasListeners, true); - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.currentSize, 0); testImageProvider.complete(); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); }); testWidgets('ScrollAwareImageProvider delays if in scrollable that is scrolling fast', (WidgetTester tester) async { @@ -173,7 +173,7 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); scrollController.animateTo( 3000, @@ -198,8 +198,8 @@ void main() { expect(testImageProvider.configuration, null); expect(stream.completer, null); - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.currentSize, 0); await tester.pump(const Duration(seconds: 1)); expect(physics.velocities.last, 0); @@ -208,12 +208,12 @@ void main() { expect(stream.completer, isNotNull); expect(stream.completer!.hasListeners, true); - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.currentSize, 0); testImageProvider.complete(); - expect(imageCache!.currentSize, 1); + expect(imageCache.currentSize, 1); }); testWidgets('ScrollAwareImageProvider delays if in scrollable that is scrolling fast and fizzles if disposed', (WidgetTester tester) async { @@ -240,7 +240,7 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); scrollController.animateTo( 3000, @@ -265,8 +265,8 @@ void main() { expect(testImageProvider.configuration, null); expect(stream.completer, null); - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.currentSize, 0); // as if we had picked a context that scrolled out of the tree. context.dispose(); @@ -277,12 +277,12 @@ void main() { expect(testImageProvider.configuration, null); expect(stream.completer, null); - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.currentSize, 0); testImageProvider.complete(); - expect(imageCache!.currentSize, 0); + expect(imageCache.currentSize, 0); }); testWidgets('ScrollAwareImageProvider resolves from ImageCache and does not set completer twice', (WidgetTester tester) async { @@ -305,7 +305,7 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); final ControllablePhysics physics = _findPhysics(tester); physics.recommendDeferredLoadingValue = true; @@ -314,28 +314,28 @@ void main() { expect(testImageProvider.configuration, null); expect(stream.completer, null); - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.currentSize, 0); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.currentSize, 0); // Simulate a case where someone else has managed to complete this stream - // so it can land in the cache right before we stop scrolling fast. // If we miss the early return, we will fail. testImageProvider.complete(); - imageCache!.putIfAbsent(testImageProvider, () => testImageProvider.load(testImageProvider, PaintingBinding.instance!.instantiateImageCodec)); + imageCache.putIfAbsent(testImageProvider, () => testImageProvider.load(testImageProvider, PaintingBinding.instance.instantiateImageCodec)); // We've stopped scrolling fast. physics.recommendDeferredLoadingValue = false; await tester.idle(); - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.currentSize, 1); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.currentSize, 1); expect(testImageProvider.loadCallCount, 1); expect(stream.completer, null); }); testWidgets('ScrollAwareImageProvider does not block LRU updates to image cache', (WidgetTester tester) async { - final int oldSize = imageCache!.maximumSize; - imageCache!.maximumSize = 1; + final int oldSize = imageCache.maximumSize; + imageCache.maximumSize = 1; final GlobalKey key = GlobalKey(); final ScrollController scrollController = ScrollController(); @@ -356,7 +356,7 @@ void main() { ); expect(testImageProvider.configuration, null); - expect(imageCache!.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider), false); final ControllablePhysics physics = _findPhysics(tester); physics.recommendDeferredLoadingValue = true; @@ -365,36 +365,36 @@ void main() { expect(testImageProvider.configuration, null); expect(stream.completer, null); - expect(imageCache!.currentSize, 0); + expect(imageCache.currentSize, 0); // Occupy the only slot in the cache with another image. final TestImageProvider testImageProvider2 = TestImageProvider(testImage); testImageProvider2.complete(); await precacheImage(testImageProvider2, context.context!); - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.containsKey(testImageProvider2), true); - expect(imageCache!.currentSize, 1); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider2), true); + expect(imageCache.currentSize, 1); // Complete the original image while we're still scrolling fast. testImageProvider.complete(); - stream.setCompleter(testImageProvider.load(testImageProvider, PaintingBinding.instance!.instantiateImageCodec)); + stream.setCompleter(testImageProvider.load(testImageProvider, PaintingBinding.instance.instantiateImageCodec)); // Verify that this hasn't changed the cache state yet - expect(imageCache!.containsKey(testImageProvider), false); - expect(imageCache!.containsKey(testImageProvider2), true); - expect(imageCache!.currentSize, 1); + expect(imageCache.containsKey(testImageProvider), false); + expect(imageCache.containsKey(testImageProvider2), true); + expect(imageCache.currentSize, 1); expect(testImageProvider.loadCallCount, 1); await tester.pump(); // After pumping a frame, the original image should be in the cache because // it took the LRU slot. - expect(imageCache!.containsKey(testImageProvider), true); - expect(imageCache!.containsKey(testImageProvider2), false); - expect(imageCache!.currentSize, 1); + expect(imageCache.containsKey(testImageProvider), true); + expect(imageCache.containsKey(testImageProvider2), false); + expect(imageCache.currentSize, 1); expect(testImageProvider.loadCallCount, 1); - imageCache!.maximumSize = oldSize; + imageCache.maximumSize = oldSize; }); } diff --git a/packages/flutter/test/widgets/scrollable_animations_test.dart b/packages/flutter/test/widgets/scrollable_animations_test.dart index fc4906a3886..117fceeaeb4 100644 --- a/packages/flutter/test/widgets/scrollable_animations_test.dart +++ b/packages/flutter/test/widgets/scrollable_animations_test.dart @@ -69,10 +69,10 @@ void main() { final double targetPosition = controller.position.pixels + doubleTolerance; controller.position.animateTo(targetPosition, duration: const Duration(seconds: 10), curve: Curves.linear); - expect(SchedulerBinding.instance!.transientCallbackCount, equals(1), reason: 'Expected an animation.'); + expect(SchedulerBinding.instance.transientCallbackCount, equals(1), reason: 'Expected an animation.'); }); } void expectNoAnimation() { - expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.'); + expect(SchedulerBinding.instance.transientCallbackCount, equals(0), reason: 'Expected no animation.'); } diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart index f3b9175f003..d8f16a0e04a 100644 --- a/packages/flutter/test/widgets/selectable_text_test.dart +++ b/packages/flutter/test/widgets/selectable_text_test.dart @@ -4451,7 +4451,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); }); testWidgets('The handles show after pressing Select All', (WidgetTester tester) async { diff --git a/packages/flutter/test/widgets/semantics_tester.dart b/packages/flutter/test/widgets/semantics_tester.dart index 506b43ac7d7..0e170efe2fc 100644 --- a/packages/flutter/test/widgets/semantics_tester.dart +++ b/packages/flutter/test/widgets/semantics_tester.dart @@ -682,7 +682,7 @@ class _HasSemantics extends Matcher { Description result = mismatchDescription .add('${matchState[TestSemantics]}\n') .add('Current SemanticsNode tree:\n') - .add(_indent(RendererBinding.instance?.renderView.debugSemantics?.toStringDeep(childOrder: childOrder))) + .add(_indent(RendererBinding.instance.renderView.debugSemantics?.toStringDeep(childOrder: childOrder))) .add('\n') .add('The semantics tree would have matched the following configuration:\n') .add(_indent(matchState['would-match'] as String)); diff --git a/packages/flutter/test/widgets/widget_inspector_test.dart b/packages/flutter/test/widgets/widget_inspector_test.dart index bebbc5749c6..1739636390b 100644 --- a/packages/flutter/test/widgets/widget_inspector_test.dart +++ b/packages/flutter/test/widgets/widget_inspector_test.dart @@ -1602,7 +1602,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { // directories so we get an empty tree other than the root that is always // included. final Object? rootWidget = service.toObject(rootJson['valueId']! as String); - expect(rootWidget, equals(WidgetsBinding.instance?.renderViewElement)); + expect(rootWidget, equals(WidgetsBinding.instance.renderViewElement)); List childrenJson = rootJson['children']! as List; // There are no summary tree children. expect(childrenJson.length, equals(0)); @@ -2495,7 +2495,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { }, ); - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final ui.Image screenshotImage = (await binding.runAsync(() async { final String base64Screenshot = (await base64ScreenshotFuture)! as String; final ui.Codec codec = await ui.instantiateImageCodec(base64.decode(base64Screenshot)); @@ -2596,7 +2596,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { // Reloads the app. final FlutterExceptionHandler? oldHandler = FlutterError.onError; - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); // We need the runTest to setup the fake async in the test binding. await binding.runTest(() async { binding.reassembleApplication(); diff --git a/packages/flutter/test/widgets/widget_inspector_test_utils.dart b/packages/flutter/test/widgets/widget_inspector_test_utils.dart index 16f57138e6d..00e99ee09b7 100644 --- a/packages/flutter/test/widgets/widget_inspector_test_utils.dart +++ b/packages/flutter/test/widgets/widget_inspector_test_utils.dart @@ -56,7 +56,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { @override Future forceRebuild() async { rebuildCount++; - final WidgetsBinding binding = WidgetsBinding.instance!; + final WidgetsBinding binding = WidgetsBinding.instance; if (binding.renderViewElement != null) { binding.buildOwner!.reassemble(binding.renderViewElement!, null); diff --git a/packages/flutter/test_fixes/cupertino.dart b/packages/flutter/test_fixes/cupertino.dart index 0c20b501fef..efc88b4d3e9 100644 --- a/packages/flutter/test_fixes/cupertino.dart +++ b/packages/flutter/test_fixes/cupertino.dart @@ -25,7 +25,7 @@ void main() { element.rootAncestorStateOfType(TypeMatcher()); element.ancestorRenderObjectOfType(TypeMatcher()); - // Changes made in https://github.com/flutter/flutter/pull/45941 + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 final WidgetsBinding binding = WidgetsBinding.instance!; binding.deferFirstFrameReport(); binding.allowFirstFrameReport(); diff --git a/packages/flutter/test_fixes/cupertino.dart.expect b/packages/flutter/test_fixes/cupertino.dart.expect index 5751b5c7b49..c20ba18822f 100644 --- a/packages/flutter/test_fixes/cupertino.dart.expect +++ b/packages/flutter/test_fixes/cupertino.dart.expect @@ -25,8 +25,8 @@ void main() { element.findRootAncestorStateOfType(); element.findAncestorRenderObjectOfType(); - // Changes made in https://github.com/flutter/flutter/pull/45941 - final WidgetsBinding binding = WidgetsBinding.instance!; + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 + final WidgetsBinding binding = WidgetsBinding.instance; binding.deferFirstFrame(); binding.allowFirstFrame(); diff --git a/packages/flutter/test_fixes/material.dart b/packages/flutter/test_fixes/material.dart index 87fdf255516..9f718a2ed6d 100644 --- a/packages/flutter/test_fixes/material.dart +++ b/packages/flutter/test_fixes/material.dart @@ -28,7 +28,7 @@ void main() { element.rootAncestorStateOfType(TypeMatcher()); element.ancestorRenderObjectOfType(TypeMatcher()); - // Changes made in https://github.com/flutter/flutter/pull/45941 + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 final WidgetsBinding binding = WidgetsBinding.instance!; binding.deferFirstFrameReport(); binding.allowFirstFrameReport(); diff --git a/packages/flutter/test_fixes/material.dart.expect b/packages/flutter/test_fixes/material.dart.expect index 7117ed89dc1..e57a31170c3 100644 --- a/packages/flutter/test_fixes/material.dart.expect +++ b/packages/flutter/test_fixes/material.dart.expect @@ -28,8 +28,8 @@ void main() { element.findRootAncestorStateOfType(); element.findAncestorRenderObjectOfType(); - // Changes made in https://github.com/flutter/flutter/pull/45941 - final WidgetsBinding binding = WidgetsBinding.instance!; + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 + final WidgetsBinding binding = WidgetsBinding.instance; binding.deferFirstFrame(); binding.allowFirstFrame(); diff --git a/packages/flutter/test_fixes/widgets.dart b/packages/flutter/test_fixes/widgets.dart index a84929a3d14..07f91484e80 100644 --- a/packages/flutter/test_fixes/widgets.dart +++ b/packages/flutter/test_fixes/widgets.dart @@ -21,8 +21,8 @@ void main() { element.rootAncestorStateOfType(TypeMatcher()); element.ancestorRenderObjectOfType(TypeMatcher()); - // Changes made in https://github.com/flutter/flutter/pull/45941 - final WidgetsBinding binding = WidgetsBinding.instance!; + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 + final WidgetsBinding binding = WidgetsBinding.instance; binding.deferFirstFrameReport(); binding.allowFirstFrameReport(); diff --git a/packages/flutter/test_fixes/widgets.dart.expect b/packages/flutter/test_fixes/widgets.dart.expect index 9cb1b10914b..e6ad6d62a70 100644 --- a/packages/flutter/test_fixes/widgets.dart.expect +++ b/packages/flutter/test_fixes/widgets.dart.expect @@ -21,8 +21,8 @@ void main() { element.findRootAncestorStateOfType(); element.findAncestorRenderObjectOfType(); - // Changes made in https://github.com/flutter/flutter/pull/45941 - final WidgetsBinding binding = WidgetsBinding.instance!; + // Changes made in https://github.com/flutter/flutter/pull/45941 and https://github.com/flutter/flutter/pull/83843 + final WidgetsBinding binding = WidgetsBinding.instance; binding.deferFirstFrame(); binding.allowFirstFrame(); diff --git a/packages/flutter_driver/lib/src/common/handler_factory.dart b/packages/flutter_driver/lib/src/common/handler_factory.dart index 41ccd3a0d75..73fed7a11d6 100644 --- a/packages/flutter_driver/lib/src/common/handler_factory.dart +++ b/packages/flutter_driver/lib/src/common/handler_factory.dart @@ -185,11 +185,11 @@ mixin CommandHandlerFactory { Future _getHealth(Command command) async => const Health(HealthStatus.ok); Future _getLayerTree(Command command) async { - return LayerTree(RendererBinding.instance?.renderView.debugLayer?.toStringDeep()); + return LayerTree(RendererBinding.instance.renderView.debugLayer?.toStringDeep()); } Future _getRenderTree(Command command) async { - return RenderTree(RendererBinding.instance?.renderView.toStringDeep()); + return RenderTree(RendererBinding.instance.renderView.toStringDeep()); } Future _enterText(Command command) async { @@ -258,8 +258,8 @@ mixin CommandHandlerFactory { 'This feature was deprecated after v1.9.3.' ) Future _waitUntilNoTransientCallbacks(Command command) async { - if (SchedulerBinding.instance!.transientCallbackCount != 0) - await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); + if (SchedulerBinding.instance.transientCallbackCount != 0) + await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); return Result.empty; } @@ -288,8 +288,8 @@ mixin CommandHandlerFactory { ) Future _waitUntilNoPendingFrame(Command command) async { await _waitUntilFrame(() { - return SchedulerBinding.instance!.transientCallbackCount == 0 - && !SchedulerBinding.instance!.hasScheduledFrame; + return SchedulerBinding.instance.transientCallbackCount == 0 + && !SchedulerBinding.instance.hasScheduledFrame; }); return Result.empty; } @@ -428,17 +428,17 @@ mixin CommandHandlerFactory { } SemanticsHandle? _semantics; - bool get _semanticsIsEnabled => RendererBinding.instance!.pipelineOwner.semanticsOwner != null; + bool get _semanticsIsEnabled => RendererBinding.instance.pipelineOwner.semanticsOwner != null; Future _setSemantics(Command command) async { final SetSemantics setSemanticsCommand = command as SetSemantics; final bool semanticsWasEnabled = _semanticsIsEnabled; if (setSemanticsCommand.enabled && _semantics == null) { - _semantics = RendererBinding.instance!.pipelineOwner.ensureSemantics(); + _semantics = RendererBinding.instance.pipelineOwner.ensureSemantics(); if (!semanticsWasEnabled) { // wait for the first frame where semantics is enabled. final Completer completer = Completer(); - SchedulerBinding.instance!.addPostFrameCallback((Duration d) { + SchedulerBinding.instance.addPostFrameCallback((Duration d) { completer.complete(); }); await completer.future; @@ -456,19 +456,19 @@ mixin CommandHandlerFactory { 'This feature was deprecated after v1.9.3.' ) Future _waitUntilFirstFrameRasterized(Command command) async { - await WidgetsBinding.instance!.waitUntilFirstFrameRasterized; + await WidgetsBinding.instance.waitUntilFirstFrameRasterized; return Result.empty; } /// Runs `finder` repeatedly until it finds one or more [Element]s. Future waitForElement(Finder finder) async { if (_frameSync) - await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); + await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => finder.evaluate().isNotEmpty); if (_frameSync) - await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); + await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); return finder; } @@ -476,12 +476,12 @@ mixin CommandHandlerFactory { /// Runs `finder` repeatedly until it finds zero [Element]s. Future waitForAbsentElement(Finder finder) async { if (_frameSync) - await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); + await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => finder.evaluate().isEmpty); if (_frameSync) - await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); + await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); return finder; } @@ -490,7 +490,7 @@ mixin CommandHandlerFactory { Future _waitUntilFrame(bool Function() condition, [ Completer? completer ]) { completer ??= Completer(); if (!condition()) { - SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { _waitUntilFrame(condition, completer); }); } else { diff --git a/packages/flutter_driver/lib/src/extension/extension.dart b/packages/flutter_driver/lib/src/extension/extension.dart index c9caa19281b..11409e47424 100644 --- a/packages/flutter_driver/lib/src/extension/extension.dart +++ b/packages/flutter_driver/lib/src/extension/extension.dart @@ -219,7 +219,6 @@ class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, /// ``` /// void enableFlutterDriverExtension({ DataHandler? handler, bool silenceErrors = false, bool enableTextEntryEmulation = true, List? finders, List? commands}) { - assert(WidgetsBinding.instance == null); _DriverBinding(handler, silenceErrors, enableTextEntryEmulation, finders ?? [], commands ?? []); assert(WidgetsBinding.instance is _DriverBinding); } @@ -334,7 +333,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, } } - final WidgetController _prober = LiveWidgetController(WidgetsBinding.instance!); + final WidgetController _prober = LiveWidgetController(WidgetsBinding.instance); final DataHandler? _requestDataHandler; @@ -364,7 +363,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, final String commandKind = params['command']!; try { final Command command = deserializeCommand(params, this); - assert(WidgetsBinding.instance!.isRootWidgetAttached || !command.requiresRootWidgetAttached, + assert(WidgetsBinding.instance.isRootWidgetAttached || !command.requiresRootWidgetAttached, 'No root widget is attached; have you remembered to call runApp()?'); Future responseFuture = handleCommand(command, _prober, this); if (command.timeout != null) diff --git a/packages/flutter_driver/lib/src/extension/wait_conditions.dart b/packages/flutter_driver/lib/src/extension/wait_conditions.dart index c5c6e69029b..8b1e1314a48 100644 --- a/packages/flutter_driver/lib/src/extension/wait_conditions.dart +++ b/packages/flutter_driver/lib/src/extension/wait_conditions.dart @@ -49,12 +49,12 @@ class _InternalNoTransientCallbacksCondition implements WaitCondition { } @override - bool get condition => SchedulerBinding.instance!.transientCallbackCount == 0; + bool get condition => SchedulerBinding.instance.transientCallbackCount == 0; @override Future wait() async { while (!condition) { - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; } assert(condition); } @@ -77,12 +77,12 @@ class _InternalNoPendingFrameCondition implements WaitCondition { } @override - bool get condition => !SchedulerBinding.instance!.hasScheduledFrame; + bool get condition => !SchedulerBinding.instance.hasScheduledFrame; @override Future wait() async { while (!condition) { - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; } assert(condition); } @@ -105,11 +105,11 @@ class _InternalFirstFrameRasterizedCondition implements WaitCondition { } @override - bool get condition => WidgetsBinding.instance!.firstFrameRasterized; + bool get condition => WidgetsBinding.instance.firstFrameRasterized; @override Future wait() async { - await WidgetsBinding.instance!.waitUntilFirstFrameRasterized; + await WidgetsBinding.instance.waitUntilFirstFrameRasterized; assert(condition); } } @@ -132,13 +132,13 @@ class _InternalNoPendingPlatformMessagesCondition implements WaitCondition { @override bool get condition { - final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger as TestDefaultBinaryMessenger; + final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger as TestDefaultBinaryMessenger; return binaryMessenger.pendingMessageCount == 0; } @override Future wait() async { - final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger as TestDefaultBinaryMessenger; + final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger as TestDefaultBinaryMessenger; while (!condition) { await binaryMessenger.platformMessagesFinished; } diff --git a/packages/flutter_driver/test/src/real_tests/extension_test.dart b/packages/flutter_driver/test/src/real_tests/extension_test.dart index 966c3141c7b..ad2f3a2aae8 100644 --- a/packages/flutter_driver/test/src/real_tests/extension_test.dart +++ b/packages/flutter_driver/test/src/real_tests/extension_test.dart @@ -55,7 +55,7 @@ void main() { }); testWidgets('waits until no transient callbacks', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrameCallback((_) { // Intentionally blank. We only care about existence of a callback. }); @@ -116,7 +116,7 @@ void main() { }); testWidgets('waiting for NoTransientCallbacks returns until no transient callbacks', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrameCallback((_) { // Intentionally blank. We only care about existence of a callback. }); @@ -158,7 +158,7 @@ void main() { }); testWidgets('waiting for NoPendingFrame returns until no pending scheduled frame', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrame(); + SchedulerBinding.instance.scheduleFrame(); driverExtension.call(const WaitForCondition(NoPendingFrame()).serialize()) .then(expectAsync1((Map r) { @@ -201,8 +201,8 @@ void main() { testWidgets( 'waiting for combined conditions returns until no transient callbacks', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrame(); - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrame(); + SchedulerBinding.instance.scheduleFrameCallback((_) { // Intentionally blank. We only care about existence of a callback. }); @@ -230,8 +230,8 @@ void main() { testWidgets( 'waiting for combined conditions returns until no pending scheduled frame', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrame(); - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrame(); + SchedulerBinding.instance.scheduleFrameCallback((_) { // Intentionally blank. We only care about existence of a callback. }); @@ -466,7 +466,7 @@ void main() { }); testWidgets('works when semantics are enabled', (WidgetTester tester) async { - final SemanticsHandle semantics = RendererBinding.instance!.pipelineOwner.ensureSemantics(); + final SemanticsHandle semantics = RendererBinding.instance.pipelineOwner.ensureSemantics(); await tester.pumpWidget( const Text('hello', textDirection: TextDirection.ltr)); @@ -490,7 +490,7 @@ void main() { }, semanticsEnabled: false); testWidgets('throws state error multiple matches are found', (WidgetTester tester) async { - final SemanticsHandle semantics = RendererBinding.instance!.pipelineOwner.ensureSemantics(); + final SemanticsHandle semantics = RendererBinding.instance.pipelineOwner.ensureSemantics(); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -1193,7 +1193,7 @@ void main() { testWidgets( 'waits until no transient callbacks', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrameCallback((_) { + SchedulerBinding.instance.scheduleFrameCallback((_) { // Intentionally blank. We only care about existence of a callback. }); @@ -1219,7 +1219,7 @@ void main() { testWidgets( 'waits until no pending scheduled frame', (WidgetTester tester) async { - SchedulerBinding.instance!.scheduleFrame(); + SchedulerBinding.instance.scheduleFrame(); driverExtension.call(const WaitForCondition(NoPendingFrame()).serialize()) .then(expectAsync1((Map r) { diff --git a/packages/flutter_test/lib/src/_binding_io.dart b/packages/flutter_test/lib/src/_binding_io.dart index f09b3e19371..0d234496642 100644 --- a/packages/flutter_test/lib/src/_binding_io.dart +++ b/packages/flutter_test/lib/src/_binding_io.dart @@ -16,18 +16,13 @@ import 'package:test_api/test_api.dart' as test_package; import 'binding.dart'; import 'deprecated.dart'; -/// Ensure the [WidgetsBinding] is initialized. -WidgetsBinding ensureInitialized([@visibleForTesting Map? environment]) { +/// Ensure the appropriate test binding is initialized. +TestWidgetsFlutterBinding ensureInitialized([@visibleForTesting Map? environment]) { environment ??= Platform.environment; - if (WidgetsBinding.instance == null) { - if (environment.containsKey('FLUTTER_TEST') && environment['FLUTTER_TEST'] != 'false') { - AutomatedTestWidgetsFlutterBinding(); - } else { - LiveTestWidgetsFlutterBinding(); - } + if (environment.containsKey('FLUTTER_TEST') && environment['FLUTTER_TEST'] != 'false') { + return AutomatedTestWidgetsFlutterBinding.ensureInitialized(); } - assert(WidgetsBinding.instance is TestWidgetsFlutterBinding); - return WidgetsBinding.instance!; + return LiveTestWidgetsFlutterBinding.ensureInitialized(); } /// Setup mocking of the global [HttpClient]. @@ -48,7 +43,7 @@ void mockFlutterAssets() { /// platform messages. SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {}); - ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { + ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { assert(message != null); String key = utf8.decode(message!.buffer.asUint8List()); File asset = File(path.join(assetFolderPath, key)); diff --git a/packages/flutter_test/lib/src/_binding_web.dart b/packages/flutter_test/lib/src/_binding_web.dart index ed87799a9f4..e2880861705 100644 --- a/packages/flutter_test/lib/src/_binding_web.dart +++ b/packages/flutter_test/lib/src/_binding_web.dart @@ -6,13 +6,9 @@ import 'package:flutter/widgets.dart'; import 'binding.dart'; -/// Ensure the [WidgetsBinding] is initialized. -WidgetsBinding ensureInitialized([@visibleForTesting Map? environment]) { - if (WidgetsBinding.instance == null) { - AutomatedTestWidgetsFlutterBinding(); - } - assert(WidgetsBinding.instance is TestWidgetsFlutterBinding); - return WidgetsBinding.instance!; +/// Ensure the appropriate test binding is initialized. +TestWidgetsFlutterBinding ensureInitialized([@visibleForTesting Map? environment]) { + return AutomatedTestWidgetsFlutterBinding.ensureInitialized(); } /// This method is a noop on the web. diff --git a/packages/flutter_test/lib/src/_matchers_io.dart b/packages/flutter_test/lib/src/_matchers_io.dart index 75d936fd435..cea07732426 100644 --- a/packages/flutter_test/lib/src/_matchers_io.dart +++ b/packages/flutter_test/lib/src/_matchers_io.dart @@ -67,7 +67,7 @@ class MatchesGoldenFile extends AsyncMatcher { final Uri testNameUri = goldenFileComparator.getTestUri(key, version); - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); return binding.runAsync(() async { final ui.Image? image = await imageFuture; if (image == null) { diff --git a/packages/flutter_test/lib/src/_matchers_web.dart b/packages/flutter_test/lib/src/_matchers_web.dart index f4c2d35319e..d2d769eafa2 100644 --- a/packages/flutter_test/lib/src/_matchers_web.dart +++ b/packages/flutter_test/lib/src/_matchers_web.dart @@ -47,7 +47,7 @@ class MatchesGoldenFile extends AsyncMatcher { final Element element = elements.single; final RenderObject renderObject = _findRepaintBoundary(element); final Size size = renderObject.paintBounds.size; - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final Element e = binding.renderViewElement!; // Unlike `flutter_tester`, we don't have the ability to render an element diff --git a/packages/flutter_test/lib/src/animation_sheet.dart b/packages/flutter_test/lib/src/animation_sheet.dart index d7c5810a796..79ceb5e852f 100644 --- a/packages/flutter_test/lib/src/animation_sheet.dart +++ b/packages/flutter_test/lib/src/animation_sheet.dart @@ -407,7 +407,7 @@ class _RenderPostFrameCallbacker extends RenderProxyBox { @override void paint(PaintingContext context, Offset offset) { if (callback != null) { - SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance.addPostFrameCallback((Duration duration) { callback!(duration); markNeedsPaint(); }); diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index 8c34a61bf93..9dde80b89d5 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -107,8 +107,11 @@ mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding { /// Base class for bindings used by widgets library tests. /// -/// The [ensureInitialized] method creates (if necessary) and returns -/// an instance of the appropriate subclass. +/// The [ensureInitialized] method creates (if necessary) and returns an +/// instance of the appropriate subclass. (If one is already created, it returns +/// that one, even if it's not the one that it would normally create. This +/// allows tests to force the use of [LiveTestWidgetsFlutterBinding] even in a +/// normal unit test environment, e.g. to test that binding.) /// /// When using these bindings, certain features are disabled. For /// example, [timeDilation] is reset to 1.0 on initialization. @@ -265,6 +268,14 @@ abstract class TestWidgetsFlutterBinding extends BindingBase /// equivalent as [Future.delayed]. Future delayed(Duration duration); + /// The current [TestWidgetsFlutterBinding], if one has been created. + /// + /// Provides access to the features exposed by this binding. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [testWidgets] or [TestWidgetsFlutterBinding.ensureInitialized]. + static TestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance); + static TestWidgetsFlutterBinding? _instance; + /// Creates and initializes the binding. This function is /// idempotent; calling it a second time will just return the /// previously-created instance. @@ -283,13 +294,26 @@ abstract class TestWidgetsFlutterBinding extends BindingBase /// [LiveTestWidgetsFlutterBinding], so this function will always set up an /// [AutomatedTestWidgetsFlutterBinding] when run in a web browser. /// - /// The parameter `environment` is exposed to test different environment - /// variable values, and should not be used. - static WidgetsBinding ensureInitialized([@visibleForTesting Map? environment]) => binding.ensureInitialized(environment); + /// The parameter `environment` is used to test the test framework + /// itself by checking how it reacts to different environment + /// variable values, and should not be used outside of this context. + /// + /// If a [TestWidgetsFlutterBinding] subclass was explicitly initialized + /// before calling [ensureInitialized], then that version of the binding is + /// returned regardless of the logic described above. This allows tests to + /// force a specific test binding to be used. + /// + /// This is called automatically by [testWidgets]. + static TestWidgetsFlutterBinding ensureInitialized([@visibleForTesting Map? environment]) { + if (_instance != null) + return _instance!; + return binding.ensureInitialized(environment); + } @override void initInstances() { super.initInstances(); + _instance = this; timeDilation = 1.0; // just in case the developer has artificially changed it for development if (overrideHttpClient) { binding.setupHttpOverrides(); @@ -894,12 +918,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase // tests. // ignore: invalid_use_of_visible_for_testing_member RawKeyboard.instance.clearKeysPressed(); - assert(!RendererBinding.instance!.mouseTracker.mouseIsConnected, + assert(!RendererBinding.instance.mouseTracker.mouseIsConnected, 'The MouseTracker thinks that there is still a mouse connected, which indicates that a ' 'test has not removed the mouse pointer which it added. Call removePointer on the ' 'active mouse gesture to remove the mouse pointer.'); // ignore: invalid_use_of_visible_for_testing_member - RendererBinding.instance!.initMouseTracker(); + RendererBinding.instance.initMouseTracker(); } } @@ -911,13 +935,41 @@ abstract class TestWidgetsFlutterBinding extends BindingBase /// /// This class assumes it is always run in checked mode (since tests are always /// run in checked mode). +/// +/// See [TestWidgetsFlutterBinding] for a list of mixins that must be +/// provided by the binding active while the test framework is +/// running. class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { @override void initInstances() { super.initInstances(); + _instance = this; binding.mockFlutterAssets(); } + /// The current [AutomatedTestWidgetsFlutterBinding], if one has been created. + /// + /// The binding must be initialized before using this getter. If you + /// need the binding to be constructed before calling [testWidgets], + /// you can ensure a binding has been constructed by calling the + /// [TestWidgetsFlutterBinding.ensureInitialized] function. + static AutomatedTestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance); + static AutomatedTestWidgetsFlutterBinding? _instance; + + /// Returns an instance of the binding that implements + /// [AutomatedTestWidgetsFlutterBinding]. If no binding has yet been + /// initialized, the a new instance is created. + /// + /// Generally, there is no need to call this method. Use + /// [TestWidgetsFlutterBinding.ensureInitialized] instead, as it + /// will select the correct test binding implementation + /// automatically. + static AutomatedTestWidgetsFlutterBinding ensureInitialized() { + if (AutomatedTestWidgetsFlutterBinding._instance == null) + AutomatedTestWidgetsFlutterBinding(); + return AutomatedTestWidgetsFlutterBinding.instance; + } + FakeAsync? _currentFakeAsync; // set in runTest; cleared in postTest Completer? _pendingAsyncTasks; @@ -1376,7 +1428,40 @@ enum LiveTestWidgetsFlutterBindingFramePolicy { /// [pump]. (There would be no point setting it to a value that /// doesn't trigger a paint, since then you could not see anything /// anyway.) +/// +/// See [TestWidgetsFlutterBinding] for a list of mixins that must be +/// provided by the binding active while the test framework is +/// running. class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { + @override + void initInstances() { + super.initInstances(); + _instance = this; + } + + /// The current [LiveTestWidgetsFlutterBinding], if one has been created. + /// + /// The binding must be initialized before using this getter. If you + /// need the binding to be constructed before calling [testWidgets], + /// you can ensure a binding has been constructed by calling the + /// [TestWidgetsFlutterBinding.ensureInitialized] function. + static LiveTestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance); + static LiveTestWidgetsFlutterBinding? _instance; + + /// Returns an instance of the binding that implements + /// [LiveTestWidgetsFlutterBinding]. If no binding has yet been + /// initialized, the a new instance is created. + /// + /// Generally, there is no need to call this method. Use + /// [TestWidgetsFlutterBinding.ensureInitialized] instead, as it + /// will select the correct test binding implementation + /// automatically. + static LiveTestWidgetsFlutterBinding ensureInitialized() { + if (LiveTestWidgetsFlutterBinding._instance == null) + LiveTestWidgetsFlutterBinding(); + return LiveTestWidgetsFlutterBinding.instance; + } + @override bool get inTest => _inTest; bool _inTest = false; diff --git a/packages/flutter_test/lib/src/finders.dart b/packages/flutter_test/lib/src/finders.dart index 8d31e978666..0bc2e1b6cd7 100644 --- a/packages/flutter_test/lib/src/finders.dart +++ b/packages/flutter_test/lib/src/finders.dart @@ -318,7 +318,7 @@ class CommonFinders { /// If the `skipOffstage` argument is true (the default), then this skips /// nodes that are [Offstage] or that are from inactive [Route]s. Finder bySemanticsLabel(Pattern label, { bool skipOffstage = true }) { - if (WidgetsBinding.instance!.pipelineOwner.semanticsOwner == null) + if (WidgetsBinding.instance.pipelineOwner.semanticsOwner == null) throw StateError('Semantics are not enabled. ' 'Make sure to call tester.ensureSemantics() before using ' 'this finder, and call dispose on its return value after.'); @@ -375,7 +375,7 @@ abstract class Finder { @protected Iterable get allCandidates { return collectAllElementsFrom( - WidgetsBinding.instance!.renderViewElement!, + WidgetsBinding.instance.renderViewElement!, skipOffstage: skipOffstage, ); } @@ -518,7 +518,7 @@ class _HitTestableFinder extends ChainedFinder { final RenderBox box = candidate.renderObject! as RenderBox; final Offset absoluteOffset = box.localToGlobal(alignment.alongSize(box.size)); final HitTestResult hitResult = HitTestResult(); - WidgetsBinding.instance!.hitTest(hitResult, absoluteOffset); + WidgetsBinding.instance.hitTest(hitResult, absoluteOffset); for (final HitTestEntry entry in hitResult.path) { if (entry.target == candidate.renderObject) { yield candidate; diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart index c2dbe5284d2..c0d84e96c3b 100644 --- a/packages/flutter_test/lib/src/matchers.dart +++ b/packages/flutter_test/lib/src/matchers.dart @@ -1677,7 +1677,7 @@ class _MatchesReferenceImage extends AsyncMatcher { imageFuture = captureImage(elements.single); } - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); return binding.runAsync(() async { final ui.Image image = await imageFuture; final ByteData? bytes = await image.toByteData(); diff --git a/packages/flutter_test/lib/src/widget_tester.dart b/packages/flutter_test/lib/src/widget_tester.dart index 055b295cacd..cab032459d0 100644 --- a/packages/flutter_test/lib/src/widget_tester.dart +++ b/packages/flutter_test/lib/src/widget_tester.dart @@ -130,7 +130,7 @@ void testWidgets( }) { assert(variant != null); assert(variant.values.isNotEmpty, 'There must be at least one value to test in the testing variant.'); - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final WidgetTester tester = WidgetTester._(binding); for (final dynamic value in variant.values) { final String variationDescription = variant.describeValue(value); @@ -404,7 +404,7 @@ Future benchmarkWidgets( print(kDebugWarning); return true; }()); - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); assert(binding is! AutomatedTestWidgetsFlutterBinding); final WidgetTester tester = WidgetTester._(binding); SemanticsHandle? semanticsHandle; diff --git a/packages/flutter_test/test/live_widget_controller_test.dart b/packages/flutter_test/test/live_widget_controller_test.dart index f1649f8af35..1079ad25484 100644 --- a/packages/flutter_test/test/live_widget_controller_test.dart +++ b/packages/flutter_test/test/live_widget_controller_test.dart @@ -68,9 +68,9 @@ void main() { test('Test pump on LiveWidgetController', () async { runApp(const MaterialApp(home: Center(child: CountButton()))); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; final WidgetController controller = - LiveWidgetController(WidgetsBinding.instance!); + LiveWidgetController(WidgetsBinding.instance); await controller.tap(find.text('Counter 0')); expect(find.text('Counter 0'), findsOneWidget); expect(find.text('Counter 1'), findsNothing); @@ -81,9 +81,9 @@ void main() { test('Test pumpAndSettle on LiveWidgetController', () async { runApp(const MaterialApp(home: Center(child: AnimateSample()))); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; final WidgetController controller = - LiveWidgetController(WidgetsBinding.instance!); + LiveWidgetController(WidgetsBinding.instance); expect(find.text('Value: 1.0'), findsNothing); await controller.pumpAndSettle(); expect(find.text('Value: 1.0'), findsOneWidget); @@ -101,9 +101,9 @@ void main() { ), ), ); - await SchedulerBinding.instance!.endOfFrame; + await SchedulerBinding.instance.endOfFrame; final WidgetController controller = - LiveWidgetController(WidgetsBinding.instance!); + LiveWidgetController(WidgetsBinding.instance); final Offset location = controller.getCenter(find.text('test')); final List records = [ diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart index c2c3636385a..76b0af63b64 100644 --- a/packages/flutter_test/test/widget_tester_test.dart +++ b/packages/flutter_test/test/widget_tester_test.dart @@ -162,7 +162,7 @@ void main() { final Widget target = _AlwaysAnimating( onPaint: () { - final int current = SchedulerBinding.instance!.currentFrameTimeStamp.inMicroseconds; + final int current = SchedulerBinding.instance.currentFrameTimeStamp.inMicroseconds; initial ??= current; logPaints.add(current - initial!); }, @@ -751,7 +751,7 @@ void main() { flutterErrorDetails = details; }; - final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); await binding.runTest(() async { final Timer timer = Timer(const Duration(seconds: 1), () {}); expect(timer.isActive, true); diff --git a/packages/flutter_test/test/window_test.dart b/packages/flutter_test/test/window_test.dart index 56a283c440a..13f5fe1ba96 100644 --- a/packages/flutter_test/test/window_test.dart +++ b/packages/flutter_test/test/window_test.dart @@ -21,7 +21,7 @@ void main() { realValue: ui.window.devicePixelRatio, fakeValue: 2.5, propertyRetriever: () { - return WidgetsBinding.instance!.window.devicePixelRatio; + return WidgetsBinding.instance.window.devicePixelRatio; }, propertyFaker: (TestWidgetsFlutterBinding binding, double fakeValue) { binding.window.devicePixelRatioTestValue = fakeValue; @@ -35,7 +35,7 @@ void main() { realValue: ui.window.physicalSize, fakeValue: const Size(50, 50), propertyRetriever: () { - return WidgetsBinding.instance!.window.physicalSize; + return WidgetsBinding.instance.window.physicalSize; }, propertyFaker: (TestWidgetsFlutterBinding binding, Size fakeValue) { binding.window.physicalSizeTestValue = fakeValue; @@ -49,7 +49,7 @@ void main() { realValue: ui.window.viewInsets, fakeValue: const FakeWindowPadding(), propertyRetriever: () { - return WidgetsBinding.instance!.window.viewInsets; + return WidgetsBinding.instance.window.viewInsets; }, propertyFaker: (TestWidgetsFlutterBinding binding, WindowPadding fakeValue) { binding.window.viewInsetsTestValue = fakeValue; @@ -63,7 +63,7 @@ void main() { realValue: ui.window.padding, fakeValue: const FakeWindowPadding(), propertyRetriever: () { - return WidgetsBinding.instance!.window.padding; + return WidgetsBinding.instance.window.padding; }, propertyFaker: (TestWidgetsFlutterBinding binding, WindowPadding fakeValue) { binding.window.paddingTestValue = fakeValue; @@ -77,7 +77,7 @@ void main() { realValue: ui.window.locale, fakeValue: const Locale('fake_language_code'), propertyRetriever: () { - return WidgetsBinding.instance!.window.locale; + return WidgetsBinding.instance.window.locale; }, propertyFaker: (TestWidgetsFlutterBinding binding, Locale fakeValue) { binding.window.localeTestValue = fakeValue; @@ -91,7 +91,7 @@ void main() { realValue: ui.window.locales, fakeValue: [const Locale('fake_language_code')], propertyRetriever: () { - return WidgetsBinding.instance!.window.locales; + return WidgetsBinding.instance.window.locales; }, propertyFaker: (TestWidgetsFlutterBinding binding, List fakeValue) { binding.window.localesTestValue = fakeValue; @@ -105,7 +105,7 @@ void main() { realValue: ui.window.textScaleFactor, fakeValue: 2.5, propertyRetriever: () { - return WidgetsBinding.instance!.window.textScaleFactor; + return WidgetsBinding.instance.window.textScaleFactor; }, propertyFaker: (TestWidgetsFlutterBinding binding, double fakeValue) { binding.window.textScaleFactorTestValue = fakeValue; @@ -119,7 +119,7 @@ void main() { realValue: ui.window.alwaysUse24HourFormat, fakeValue: !ui.window.alwaysUse24HourFormat, propertyRetriever: () { - return WidgetsBinding.instance!.window.alwaysUse24HourFormat; + return WidgetsBinding.instance.window.alwaysUse24HourFormat; }, propertyFaker: (TestWidgetsFlutterBinding binding, bool fakeValue) { binding.window.alwaysUse24HourFormatTestValue = fakeValue; @@ -133,7 +133,7 @@ void main() { realValue: ui.window.defaultRouteName, fakeValue: 'fake_route', propertyRetriever: () { - return WidgetsBinding.instance!.window.defaultRouteName; + return WidgetsBinding.instance.window.defaultRouteName; }, propertyFaker: (TestWidgetsFlutterBinding binding, String fakeValue) { binding.window.defaultRouteNameTestValue = fakeValue; @@ -147,7 +147,7 @@ void main() { realValue: ui.window.accessibilityFeatures, fakeValue: const FakeAccessibilityFeatures(), propertyRetriever: () { - return WidgetsBinding.instance!.window.accessibilityFeatures; + return WidgetsBinding.instance.window.accessibilityFeatures; }, propertyFaker: (TestWidgetsFlutterBinding binding, AccessibilityFeatures fakeValue) { binding.window.accessibilityFeaturesTestValue = fakeValue; @@ -161,7 +161,7 @@ void main() { realValue: Brightness.light, fakeValue: Brightness.dark, propertyRetriever: () { - return WidgetsBinding.instance!.window.platformBrightness; + return WidgetsBinding.instance.window.platformBrightness; }, propertyFaker: (TestWidgetsFlutterBinding binding, Brightness fakeValue) { binding.window.platformBrightnessTestValue = fakeValue; @@ -182,8 +182,8 @@ void main() { testWindow.clearAllTestValues(); // Verify that the window once again reports real property values. - expect(WidgetsBinding.instance!.window.devicePixelRatio, originalDevicePixelRatio); - expect(WidgetsBinding.instance!.window.textScaleFactor, originalTextScaleFactor); + expect(WidgetsBinding.instance.window.devicePixelRatio, originalDevicePixelRatio); + expect(WidgetsBinding.instance.window.textScaleFactor, originalTextScaleFactor); }); testWidgets('TestWindow sends fake locales when WidgetsBindingObserver notifiers are called', (WidgetTester tester) async { diff --git a/packages/flutter_web_plugins/test/plugin_registry_test.dart b/packages/flutter_web_plugins/test/plugin_registry_test.dart index 73cb681e07c..0bd67fc00f5 100644 --- a/packages/flutter_web_plugins/test/plugin_registry_test.dart +++ b/packages/flutter_web_plugins/test/plugin_registry_test.dart @@ -54,7 +54,7 @@ void main() { const StandardMessageCodec codec = StandardMessageCodec(); final List loggedMessages = []; - ServicesBinding.instance!.defaultBinaryMessenger + ServicesBinding.instance.defaultBinaryMessenger .setMessageHandler('test_send', (ByteData? data) { loggedMessages.add(codec.decodeMessage(data)! as String); return Future.value(null); @@ -68,7 +68,7 @@ void main() { 'test_send', codec.encodeMessage('world')); expect(loggedMessages, equals(['hello', 'world'])); - ServicesBinding.instance!.defaultBinaryMessenger + ServicesBinding.instance.defaultBinaryMessenger .setMessageHandler('test_send', null); }); }); diff --git a/packages/integration_test/example/integration_test/_example_test_io.dart b/packages/integration_test/example/integration_test/_example_test_io.dart index 8daf8c8f686..7f56cd788ff 100644 --- a/packages/integration_test/example/integration_test/_example_test_io.dart +++ b/packages/integration_test/example/integration_test/_example_test_io.dart @@ -17,9 +17,7 @@ import 'package:integration_test/integration_test.dart'; import 'package:integration_test_example/main.dart' as app; void main() { - final IntegrationTestWidgetsFlutterBinding binding = - IntegrationTestWidgetsFlutterBinding.ensureInitialized() - as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets('verify text', (WidgetTester tester) async { // Build our app and trigger a frame. app.main(); diff --git a/packages/integration_test/example/integration_test/_extended_test_web.dart b/packages/integration_test/example/integration_test/_extended_test_web.dart index 1b5d03e5467..b95b157073f 100644 --- a/packages/integration_test/example/integration_test/_extended_test_web.dart +++ b/packages/integration_test/example/integration_test/_extended_test_web.dart @@ -17,7 +17,7 @@ import 'package:integration_test/integration_test.dart'; import 'package:integration_test_example/main.dart' as app; void main() { - final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets('verify text', (WidgetTester tester) async { // Build our app and trigger a frame. diff --git a/packages/integration_test/lib/integration_test.dart b/packages/integration_test/lib/integration_test.dart index 76aa7b2bc73..112646d3978 100644 --- a/packages/integration_test/lib/integration_test.dart +++ b/packages/integration_test/lib/integration_test.dart @@ -132,16 +132,30 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab @override List get failureMethodsDetails => results.values.whereType().toList(); - /// Similar to [WidgetsFlutterBinding.ensureInitialized]. + @override + void initInstances() { + super.initInstances(); + _instance = this; + } + + /// The singleton instance of this object. /// + /// Provides access to the features exposed by this class. The binding must + /// be initialized before using this getter; this is typically done by calling + /// [IntegrationTestWidgetsFlutterBinding.ensureInitialized]. + static IntegrationTestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance); + static IntegrationTestWidgetsFlutterBinding? _instance; + /// Returns an instance of the [IntegrationTestWidgetsFlutterBinding], creating and /// initializing it if necessary. - static WidgetsBinding ensureInitialized() { - if (WidgetsBinding.instance == null) { + /// + /// See also: + /// + /// * [WidgetsFlutterBinding.ensureInitialized], the equivalent in the widgets framework. + static IntegrationTestWidgetsFlutterBinding ensureInitialized() { + if (_instance == null) IntegrationTestWidgetsFlutterBinding(); - } - assert(WidgetsBinding.instance is IntegrationTestWidgetsFlutterBinding); - return WidgetsBinding.instance!; + return _instance!; } static const MethodChannel _channel = diff --git a/packages/integration_test/test/binding_fail_test.dart b/packages/integration_test/test/binding_fail_test.dart index a7ceb4b2504..d293f56cc06 100644 --- a/packages/integration_test/test/binding_fail_test.dart +++ b/packages/integration_test/test/binding_fail_test.dart @@ -10,8 +10,7 @@ import 'package:path/path.dart' as path; final String bat = Platform.isWindows ? '.bat' : ''; final String _flutterBin = path.join(Directory.current.parent.parent.path, 'bin', 'flutter$bat'); -const String _integrationResultsPrefix = - 'IntegrationTestWidgetsFlutterBinding test results:'; +const String _integrationResultsPrefix = 'IntegrationTestWidgetsFlutterBinding test results:'; const String _failureExcerpt = r'Expected: \n Actual: '; Future main() async { diff --git a/packages/integration_test/test/binding_test.dart b/packages/integration_test/test/binding_test.dart index 83d48137430..ec90a54abdf 100644 --- a/packages/integration_test/test/binding_test.dart +++ b/packages/integration_test/test/binding_test.dart @@ -20,14 +20,12 @@ Future main() async { Future>? request; group('Test Integration binding', () { - final WidgetsBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - assert(binding is IntegrationTestWidgetsFlutterBinding); - final IntegrationTestWidgetsFlutterBinding integrationBinding = binding as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); FakeVM? fakeVM; setUp(() { - request = integrationBinding.callback({ + request = binding.callback({ 'command': 'request_data', }); fakeVM = FakeVM( @@ -39,8 +37,8 @@ Future main() async { runApp(const MaterialApp( home: Text('Test'), )); - expect(tester.binding, integrationBinding); - integrationBinding.reportData = {'answer': 42}; + expect(tester.binding, binding); + binding.reportData = {'answer': 42}; }); testWidgets('setSurfaceSize works', (WidgetTester tester) async { @@ -70,26 +68,26 @@ Future main() async { }); testWidgets('Test traceAction', (WidgetTester tester) async { - await integrationBinding.enableTimeline(vmService: fakeVM); - await integrationBinding.traceAction(() async {}); - expect(integrationBinding.reportData, isNotNull); - expect(integrationBinding.reportData!.containsKey('timeline'), true); + await binding.enableTimeline(vmService: fakeVM); + await binding.traceAction(() async {}); + expect(binding.reportData, isNotNull); + expect(binding.reportData!.containsKey('timeline'), true); expect( - json.encode(integrationBinding.reportData!['timeline']), + json.encode(binding.reportData!['timeline']), json.encode(_kTimelines), ); }); group('defaultTestTimeout', () { - final Timeout originalTimeout = integrationBinding.defaultTestTimeout; + final Timeout originalTimeout = binding.defaultTestTimeout; tearDown(() { - integrationBinding.defaultTestTimeout = originalTimeout; + binding.defaultTestTimeout = originalTimeout; }); test('can be configured', () { const Timeout newTimeout = Timeout(Duration(seconds: 17)); - integrationBinding.defaultTestTimeout = newTimeout; - expect(integrationBinding.defaultTestTimeout, newTimeout); + binding.defaultTestTimeout = newTimeout; + expect(binding.defaultTestTimeout, newTimeout); }); }); diff --git a/packages/integration_test/test/data/fail_test_script.dart b/packages/integration_test/test/data/fail_test_script.dart index c2c5f6302e6..65a3a14999e 100644 --- a/packages/integration_test/test/data/fail_test_script.dart +++ b/packages/integration_test/test/data/fail_test_script.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; Future main() async { - final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); binding.allTestsPassed.future.then((_) { print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); }); diff --git a/packages/integration_test/test/data/fail_then_pass_test_script.dart b/packages/integration_test/test/data/fail_then_pass_test_script.dart index df97bc474f8..2f2e4caf6c7 100644 --- a/packages/integration_test/test/data/fail_then_pass_test_script.dart +++ b/packages/integration_test/test/data/fail_then_pass_test_script.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; Future main() async { - final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); binding.allTestsPassed.future.then((_) { print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); }); diff --git a/packages/integration_test/test/data/pass_test_script.dart b/packages/integration_test/test/data/pass_test_script.dart index 3ab5040cc72..79185bd0705 100644 --- a/packages/integration_test/test/data/pass_test_script.dart +++ b/packages/integration_test/test/data/pass_test_script.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; Future main() async { - final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); binding.allTestsPassed.future.then((_) { print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); }); diff --git a/packages/integration_test/test/data/pass_then_fail_test_script.dart b/packages/integration_test/test/data/pass_then_fail_test_script.dart index c87bc00f577..39ab6a2158b 100644 --- a/packages/integration_test/test/data/pass_then_fail_test_script.dart +++ b/packages/integration_test/test/data/pass_then_fail_test_script.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; Future main() async { - final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); binding.allTestsPassed.future.then((_) { print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); });