mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Clean up the bindings APIs (#86438)
This commit is contained in:
parent
666185c027
commit
d056500bfe
@ -32,7 +32,7 @@ Future<void> main() async {
|
|||||||
child: ComplexLayoutApp(),
|
child: ComplexLayoutApp(),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
await SchedulerBinding.instance?.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
|
|
||||||
/// Wait 50ms to allow the raster thread to actually put up the frame. (The
|
/// 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
|
/// endOfFrame future ends when we send the data to the engine, before
|
||||||
@ -50,9 +50,9 @@ Future<void> main() async {
|
|||||||
child: ComplexLayoutApp(),
|
child: ComplexLayoutApp(),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
await SchedulerBinding.instance?.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
|
|
||||||
final WidgetController controller = LiveWidgetController(WidgetsBinding.instance!);
|
final WidgetController controller = LiveWidgetController(WidgetsBinding.instance);
|
||||||
|
|
||||||
// Scroll down
|
// Scroll down
|
||||||
for (int iteration = 0; iteration < maxIterations; iteration += 1) {
|
for (int iteration = 0; iteration < maxIterations; iteration += 1) {
|
||||||
|
@ -41,7 +41,7 @@ class _FilteredChildAnimationPageState extends State<FilteredChildAnimationPage>
|
|||||||
_filterType = widget.initialFilterType;
|
_filterType = widget.initialFilterType;
|
||||||
_complexChild = widget.initialComplexChild;
|
_complexChild = widget.initialComplexChild;
|
||||||
_useRepaintBoundary = widget.initialUseRepaintBoundary;
|
_useRepaintBoundary = widget.initialUseRepaintBoundary;
|
||||||
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
final RenderBox childBox = _childKey.currentContext!.findRenderObject()! as RenderBox;
|
final RenderBox childBox = _childKey.currentContext!.findRenderObject()! as RenderBox;
|
||||||
_childCenter = childBox.paintBounds.center;
|
_childCenter = childBox.paintBounds.center;
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,7 @@ class LargeImagesPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ImageCache imageCache = PaintingBinding.instance!.imageCache!;
|
final ImageCache imageCache = PaintingBinding.instance.imageCache;
|
||||||
imageCache.maximumSize = 30;
|
imageCache.maximumSize = 30;
|
||||||
imageCache.maximumSizeBytes = 50 << 20;
|
imageCache.maximumSizeBytes = 50 << 20;
|
||||||
return GridView.builder(
|
return GridView.builder(
|
||||||
|
@ -66,7 +66,7 @@ class BenchMouseRegionGridHover extends WidgetRecorder {
|
|||||||
void frameDidDraw() {
|
void frameDidDraw() {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async {
|
||||||
_tester.start();
|
_tester.start();
|
||||||
registerDidStop(_tester.stop);
|
registerDidStop(_tester.stop);
|
||||||
});
|
});
|
||||||
@ -124,7 +124,7 @@ class _UntilNextFrame {
|
|||||||
static Future<void> wait() {
|
static Future<void> wait() {
|
||||||
if (_UntilNextFrame._completer == null) {
|
if (_UntilNextFrame._completer == null) {
|
||||||
_UntilNextFrame._completer = Completer<void>();
|
_UntilNextFrame._completer = Completer<void>();
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
_UntilNextFrame._completer!.complete(null);
|
_UntilNextFrame._completer!.complete(null);
|
||||||
_UntilNextFrame._completer = null;
|
_UntilNextFrame._completer = null;
|
||||||
});
|
});
|
||||||
@ -145,7 +145,7 @@ class _Tester {
|
|||||||
TestGesture get gesture {
|
TestGesture get gesture {
|
||||||
return _gesture ??= TestGesture(
|
return _gesture ??= TestGesture(
|
||||||
dispatcher: (PointerEvent event) async {
|
dispatcher: (PointerEvent event) async {
|
||||||
RendererBinding.instance!.handlePointerEvent(event);
|
RendererBinding.instance.handlePointerEvent(event);
|
||||||
},
|
},
|
||||||
kind: PointerDeviceKind.mouse,
|
kind: PointerDeviceKind.mouse,
|
||||||
);
|
);
|
||||||
|
@ -41,7 +41,7 @@ class BenchMouseRegionGridScroll extends WidgetRecorder {
|
|||||||
void frameDidDraw() {
|
void frameDidDraw() {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async {
|
||||||
_tester.start();
|
_tester.start();
|
||||||
registerDidStop(_tester.stop);
|
registerDidStop(_tester.stop);
|
||||||
});
|
});
|
||||||
@ -96,7 +96,7 @@ class _UntilNextFrame {
|
|||||||
static Future<void> wait() {
|
static Future<void> wait() {
|
||||||
if (_UntilNextFrame._completer == null) {
|
if (_UntilNextFrame._completer == null) {
|
||||||
_UntilNextFrame._completer = Completer<void>();
|
_UntilNextFrame._completer = Completer<void>();
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
_UntilNextFrame._completer!.complete(null);
|
_UntilNextFrame._completer!.complete(null);
|
||||||
_UntilNextFrame._completer = null;
|
_UntilNextFrame._completer = null;
|
||||||
});
|
});
|
||||||
@ -117,7 +117,7 @@ class _Tester {
|
|||||||
TestGesture get gesture {
|
TestGesture get gesture {
|
||||||
return _gesture ??= TestGesture(
|
return _gesture ??= TestGesture(
|
||||||
dispatcher: (PointerEvent event) async {
|
dispatcher: (PointerEvent event) async {
|
||||||
RendererBinding.instance!.handlePointerEvent(event);
|
RendererBinding.instance.handlePointerEvent(event);
|
||||||
},
|
},
|
||||||
kind: PointerDeviceKind.mouse,
|
kind: PointerDeviceKind.mouse,
|
||||||
);
|
);
|
||||||
|
@ -85,7 +85,7 @@ class BenchMouseRegionMixedGridHover extends WidgetRecorder {
|
|||||||
void frameDidDraw() {
|
void frameDidDraw() {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) async {
|
||||||
_tester.start();
|
_tester.start();
|
||||||
registerDidStop(_tester.stop);
|
registerDidStop(_tester.stop);
|
||||||
});
|
});
|
||||||
@ -146,7 +146,7 @@ class _UntilNextFrame {
|
|||||||
static Future<void> wait() {
|
static Future<void> wait() {
|
||||||
if (_UntilNextFrame._completer == null) {
|
if (_UntilNextFrame._completer == null) {
|
||||||
_UntilNextFrame._completer = Completer<void>();
|
_UntilNextFrame._completer = Completer<void>();
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
_UntilNextFrame._completer!.complete(null);
|
_UntilNextFrame._completer!.complete(null);
|
||||||
_UntilNextFrame._completer = null;
|
_UntilNextFrame._completer = null;
|
||||||
});
|
});
|
||||||
@ -167,7 +167,7 @@ class _Tester {
|
|||||||
TestGesture get gesture {
|
TestGesture get gesture {
|
||||||
return _gesture ??= TestGesture(
|
return _gesture ??= TestGesture(
|
||||||
dispatcher: (PointerEvent event) async {
|
dispatcher: (PointerEvent event) async {
|
||||||
RendererBinding.instance!.handlePointerEvent(event);
|
RendererBinding.instance.handlePointerEvent(event);
|
||||||
},
|
},
|
||||||
kind: PointerDeviceKind.mouse,
|
kind: PointerDeviceKind.mouse,
|
||||||
);
|
);
|
||||||
|
@ -935,7 +935,7 @@ double _computeAverage(String label, Iterable<double> values) {
|
|||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * https://en.wikipedia.org/wiki/Standard_deviation
|
/// * <https://en.wikipedia.org/wiki/Standard_deviation>
|
||||||
double _computeStandardDeviationForPopulation(String label, Iterable<double> population) {
|
double _computeStandardDeviationForPopulation(String label, Iterable<double> population) {
|
||||||
if (population.isEmpty) {
|
if (population.isEmpty) {
|
||||||
throw StateError('$label: attempted to compute the standard deviation of empty population.');
|
throw StateError('$label: attempted to compute the standard deviation of empty population.');
|
||||||
@ -987,12 +987,32 @@ class _RecordingWidgetsBinding extends BindingBase
|
|||||||
SemanticsBinding,
|
SemanticsBinding,
|
||||||
RendererBinding,
|
RendererBinding,
|
||||||
WidgetsBinding {
|
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() {
|
static _RecordingWidgetsBinding ensureInitialized() {
|
||||||
if (WidgetsBinding.instance == null) {
|
if (_instance == null) {
|
||||||
_RecordingWidgetsBinding();
|
_RecordingWidgetsBinding();
|
||||||
}
|
}
|
||||||
return WidgetsBinding.instance! as _RecordingWidgetsBinding;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameRecorder? _recorder;
|
FrameRecorder? _recorder;
|
||||||
|
@ -10,8 +10,7 @@ import 'package:integration_test/integration_test.dart';
|
|||||||
import 'package:macrobenchmarks/src/simple_scroll.dart';
|
import 'package:macrobenchmarks/src/simple_scroll.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final IntegrationTestWidgetsFlutterBinding binding =
|
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'Frame Counter and Input Delay for benchmarkLive',
|
'Frame Counter and Input Delay for benchmarkLive',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
@ -10,8 +10,8 @@ import 'package:macrobenchmarks/main.dart';
|
|||||||
|
|
||||||
Future<void> endOfAnimation() async {
|
Future<void> endOfAnimation() async {
|
||||||
do {
|
do {
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
} while (SchedulerBinding.instance!.hasScheduledFrame);
|
} while (SchedulerBinding.instance.hasScheduledFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
@ -10,8 +10,8 @@ import 'package:macrobenchmarks/main.dart';
|
|||||||
|
|
||||||
Future<void> endOfAnimation() async {
|
Future<void> endOfAnimation() async {
|
||||||
do {
|
do {
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
} while (SchedulerBinding.instance!.hasScheduledFrame);
|
} while (SchedulerBinding.instance.hasScheduledFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
@ -44,24 +44,24 @@ Future<void> main() async {
|
|||||||
|
|
||||||
// Wait for frame rendering to stabilize.
|
// Wait for frame rendering to stabilize.
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
await SchedulerBinding.instance?.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Stopwatch watch = Stopwatch();
|
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
|
// 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) {
|
while (elementCount < 2458) {
|
||||||
await Future<void>.delayed(Duration.zero);
|
await Future<void>.delayed(Duration.zero);
|
||||||
elementCount = collectAllElementsFrom(WidgetsBinding.instance!.renderViewElement!, skipOffstage: false).length;
|
elementCount = collectAllElementsFrom(WidgetsBinding.instance.renderViewElement!, skipOffstage: false).length;
|
||||||
}
|
}
|
||||||
print('element count: $elementCount');
|
print('element count: $elementCount');
|
||||||
|
|
||||||
watch.start();
|
watch.start();
|
||||||
for (int i = 0; i < _kNumIters; i += 1) {
|
for (int i = 0; i < _kNumIters; i += 1) {
|
||||||
final List<Element> allElements = collectAllElementsFrom(
|
final List<Element> allElements = collectAllElementsFrom(
|
||||||
WidgetsBinding.instance!.renderViewElement!,
|
WidgetsBinding.instance.renderViewElement!,
|
||||||
skipOffstage: false,
|
skipOffstage: false,
|
||||||
).toList();
|
).toList();
|
||||||
allElements.clear();
|
allElements.clear();
|
||||||
|
@ -68,7 +68,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
// Time how long each frame takes
|
// Time how long each frame takes
|
||||||
cpuWatch.reset();
|
cpuWatch.reset();
|
||||||
while (SchedulerBinding.instance!.hasScheduledFrame) {
|
while (SchedulerBinding.instance.hasScheduledFrame) {
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
totalSubsequentFramesIterationCount += 1;
|
totalSubsequentFramesIterationCount += 1;
|
||||||
}
|
}
|
||||||
|
@ -33,18 +33,18 @@ Future<void> main() async {
|
|||||||
|
|
||||||
final TestViewConfiguration big = TestViewConfiguration(
|
final TestViewConfiguration big = TestViewConfiguration(
|
||||||
size: const Size(360.0, 640.0),
|
size: const Size(360.0, 640.0),
|
||||||
window: RendererBinding.instance?.window,
|
window: RendererBinding.instance.window,
|
||||||
);
|
);
|
||||||
final TestViewConfiguration small = TestViewConfiguration(
|
final TestViewConfiguration small = TestViewConfiguration(
|
||||||
size: const Size(355.0, 635.0),
|
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;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.benchmark;
|
||||||
|
|
||||||
watch.start();
|
watch.start();
|
||||||
while (watch.elapsed < kBenchmarkTime) {
|
while (watch.elapsed < kBenchmarkTime) {
|
||||||
renderView?.configuration = iterations.isEven ? big : small;
|
renderView.configuration = iterations.isEven ? big : small;
|
||||||
await tester.pumpBenchmark(Duration(milliseconds: iterations * 16));
|
await tester.pumpBenchmark(Duration(milliseconds: iterations * 16));
|
||||||
iterations += 1;
|
iterations += 1;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class _HomePage extends State<HomePage> {
|
|||||||
|
|
||||||
// Trigger the second route.
|
// Trigger the second route.
|
||||||
// https://github.com/flutter/flutter/issues/40126
|
// https://github.com/flutter/flutter/issues/40126
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(builder: (_) => const SecondPage()));
|
MaterialPageRoute<void>(builder: (_) => const SecondPage()));
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_gallery/demo/calculator_demo.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import 'package:flutter_gallery/gallery/app.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
print('Starting app...');
|
print('Starting app...');
|
||||||
runApp(const GalleryApp(testMode: true));
|
runApp(const GalleryApp(testMode: true));
|
||||||
final _LiveWidgetController controller = _LiveWidgetController(WidgetsBinding.instance!);
|
final _LiveWidgetController controller = _LiveWidgetController(WidgetsBinding.instance);
|
||||||
for (final GalleryDemoCategory category in kAllGalleryDemoCategories) {
|
for (final GalleryDemoCategory category in kAllGalleryDemoCategories) {
|
||||||
print('Tapping "${category.name}" section...');
|
print('Tapping "${category.name}" section...');
|
||||||
await controller.tap(find.text(category.name));
|
await controller.tap(find.text(category.name));
|
||||||
@ -111,7 +111,7 @@ class _LiveWidgetController extends LiveWidgetController {
|
|||||||
Future<void> _waitUntilFrame(bool Function() condition, [Completer<void>? completer]) {
|
Future<void> _waitUntilFrame(bool Function() condition, [Completer<void>? completer]) {
|
||||||
completer ??= Completer<void>();
|
completer ??= Completer<void>();
|
||||||
if (!condition()) {
|
if (!condition()) {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
|
||||||
_waitUntilFrame(condition, completer);
|
_waitUntilFrame(condition, completer);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_gallery/gallery/app.dart' show GalleryApp;
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -77,9 +77,9 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async {
|
|||||||
|
|
||||||
// Verify that the dumps are pretty.
|
// Verify that the dumps are pretty.
|
||||||
final String routeName = demo.routeName;
|
final String routeName = demo.routeName;
|
||||||
verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance!.renderViewElement!.toStringDeep());
|
verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance.renderViewElement!.toStringDeep());
|
||||||
verifyToStringOutput('debugDumpRenderTree', routeName, RendererBinding.instance?.renderView.toStringDeep() ?? '');
|
verifyToStringOutput('debugDumpRenderTree', routeName, RendererBinding.instance.renderView.toStringDeep());
|
||||||
verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? '');
|
verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance.renderView.debugLayer?.toStringDeep() ?? '');
|
||||||
|
|
||||||
// Scroll the demo around a bit more.
|
// Scroll the demo around a bit more.
|
||||||
await tester.flingFrom(const Offset(400.0, 300.0), const Offset(0.0, 400.0), 1000.0);
|
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', smokeGallery);
|
||||||
|
|
||||||
testWidgets('Flutter Gallery app smoke test with semantics', (WidgetTester tester) async {
|
testWidgets('Flutter Gallery app smoke test with semantics', (WidgetTester tester) async {
|
||||||
RendererBinding.instance!.setSemanticsEnabled(true);
|
RendererBinding.instance.setSemanticsEnabled(true);
|
||||||
await smokeGallery(tester);
|
await smokeGallery(tester);
|
||||||
RendererBinding.instance!.setSemanticsEnabled(false);
|
RendererBinding.instance.setSemanticsEnabled(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ Future<String> mockUpdateUrlFetcher() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
if (binding is LiveTestWidgetsFlutterBinding)
|
if (binding is LiveTestWidgetsFlutterBinding)
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ class _MessageHandler {
|
|||||||
case 'demoNames':
|
case 'demoNames':
|
||||||
return const JsonEncoder.withIndent(' ').convert(_allDemos);
|
return const JsonEncoder.withIndent(' ').convert(_allDemos);
|
||||||
case 'profileDemos':
|
case 'profileDemos':
|
||||||
controller ??= LiveWidgetController(WidgetsBinding.instance!);
|
controller ??= LiveWidgetController(WidgetsBinding.instance);
|
||||||
await runDemos(kProfiledDemos, controller!);
|
await runDemos(kProfiledDemos, controller!);
|
||||||
_unTestedDemos.removeAll(kProfiledDemos);
|
_unTestedDemos.removeAll(kProfiledDemos);
|
||||||
return const JsonEncoder.withIndent(' ').convert(kProfiledDemos);
|
return const JsonEncoder.withIndent(' ').convert(kProfiledDemos);
|
||||||
case 'restDemos':
|
case 'restDemos':
|
||||||
controller ??= LiveWidgetController(WidgetsBinding.instance!);
|
controller ??= LiveWidgetController(WidgetsBinding.instance);
|
||||||
final List<String> restDemos = _unTestedDemos.toList();
|
final List<String> restDemos = _unTestedDemos.toList();
|
||||||
await runDemos(restDemos, controller!);
|
await runDemos(restDemos, controller!);
|
||||||
return const JsonEncoder.withIndent(' ').convert(restDemos);
|
return const JsonEncoder.withIndent(' ').convert(restDemos);
|
||||||
|
@ -22,8 +22,7 @@ List<String> _allDemos = kAllGalleryDemos.map(
|
|||||||
|
|
||||||
void main([List<String> args = const <String>[]]) {
|
void main([List<String> args = const <String>[]]) {
|
||||||
final bool withSemantics = args.contains('--with_semantics');
|
final bool withSemantics = args.contains('--with_semantics');
|
||||||
final IntegrationTestWidgetsFlutterBinding binding =
|
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
|
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
group('flutter gallery transitions on e2e', () {
|
group('flutter gallery transitions on e2e', () {
|
||||||
testWidgets('find.bySemanticsLabel', (WidgetTester tester) async {
|
testWidgets('find.bySemanticsLabel', (WidgetTester tester) async {
|
||||||
|
@ -11,8 +11,8 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
Future<void> endOfAnimation() async {
|
Future<void> endOfAnimation() async {
|
||||||
do {
|
do {
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
} while (SchedulerBinding.instance!.hasScheduledFrame);
|
} while (SchedulerBinding.instance.hasScheduledFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
@ -30,5 +30,5 @@ Future<void> main() async {
|
|||||||
await endOfAnimation();
|
await endOfAnimation();
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||||
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
||||||
WidgetsBinding.instance!.addObserver(LifecycleObserver());
|
WidgetsBinding.instance.addObserver(LifecycleObserver());
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ Future<void> main() async {
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
|
|
||||||
// We are waiting for the GPU to rasterize a frame here. This makes this
|
// 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
|
// flaky, we can rely on a more deterministic source such as
|
||||||
@ -48,7 +48,7 @@ Future<void> main() async {
|
|||||||
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
||||||
|
|
||||||
final WidgetController controller =
|
final WidgetController controller =
|
||||||
LiveWidgetController(WidgetsBinding.instance!);
|
LiveWidgetController(WidgetsBinding.instance);
|
||||||
|
|
||||||
debugPrint('Scrolling...');
|
debugPrint('Scrolling...');
|
||||||
final Finder list = find.byKey(const Key('ImageList'));
|
final Finder list = find.byKey(const Key('ImageList'));
|
||||||
|
@ -13,8 +13,8 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
Future<void> endOfAnimation() async {
|
Future<void> endOfAnimation() async {
|
||||||
do {
|
do {
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
} while (SchedulerBinding.instance!.hasScheduledFrame);
|
} while (SchedulerBinding.instance.hasScheduledFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect boundsFor(WidgetController controller, Finder item) {
|
Rect boundsFor(WidgetController controller, Finder item) {
|
||||||
@ -35,7 +35,7 @@ Future<void> main() async {
|
|||||||
child: GalleryApp(testMode: true),
|
child: GalleryApp(testMode: true),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
await SchedulerBinding.instance!.endOfFrame;
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||||
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
debugPrint('==== MEMORY BENCHMARK ==== READY ====');
|
||||||
|
|
||||||
@ -49,9 +49,9 @@ Future<void> main() async {
|
|||||||
child: GalleryApp(testMode: true),
|
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...');
|
debugPrint('Navigating...');
|
||||||
await controller.tap(find.text('Material'));
|
await controller.tap(find.text('Material'));
|
||||||
|
@ -16,7 +16,7 @@ void main() {
|
|||||||
// Disconnects semantics listener for testing purposes.
|
// Disconnects semantics listener for testing purposes.
|
||||||
originalSemanticsListener = ui.window.onSemanticsEnabledChanged;
|
originalSemanticsListener = ui.window.onSemanticsEnabledChanged;
|
||||||
ui.window.onSemanticsEnabledChanged = null;
|
ui.window.onSemanticsEnabledChanged = null;
|
||||||
RendererBinding.instance?.setSemanticsEnabled(false);
|
RendererBinding.instance.setSemanticsEnabled(false);
|
||||||
// If the test passes, LifeCycleSpy will rewire the semantics listener back.
|
// If the test passes, LifeCycleSpy will rewire the semantics listener back.
|
||||||
runApp(const LifeCycleSpy());
|
runApp(const LifeCycleSpy());
|
||||||
}
|
}
|
||||||
@ -46,15 +46,15 @@ class _LifeCycleSpyState extends State<LifeCycleSpy> with WidgetsBindingObserver
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance?.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
_actualLifeCycleSequence = <AppLifecycleState?>[
|
_actualLifeCycleSequence = <AppLifecycleState?>[
|
||||||
ServicesBinding.instance?.lifecycleState
|
ServicesBinding.instance.lifecycleState
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance?.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ class _LifeCycleSpyState extends State<LifeCycleSpy> with WidgetsBindingObserver
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (const ListEquality<AppLifecycleState?>().equals(_actualLifeCycleSequence, _expectedLifeCycleSequence)) {
|
if (const ListEquality<AppLifecycleState?>().equals(_actualLifeCycleSequence, _expectedLifeCycleSequence)) {
|
||||||
// Rewires the semantics harness if test passes.
|
// Rewires the semantics harness if test passes.
|
||||||
RendererBinding.instance?.setSemanticsEnabled(true);
|
RendererBinding.instance.setSemanticsEnabled(true);
|
||||||
ui.window.onSemanticsEnabledChanged = originalSemanticsListener;
|
ui.window.onSemanticsEnabledChanged = originalSemanticsListener;
|
||||||
}
|
}
|
||||||
return const MaterialApp(
|
return const MaterialApp(
|
||||||
|
@ -960,7 +960,7 @@ class _PaintingState extends State<Painting> with SingleTickerProviderStateMixin
|
|||||||
}
|
}
|
||||||
_text = buffer.toString();
|
_text = buffer.toString();
|
||||||
});
|
});
|
||||||
SchedulerBinding.instance?.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
if (mounted && intrinsicKey.currentContext?.size?.height != controlKey.currentContext?.size?.height) {
|
if (mounted && intrinsicKey.currentContext?.size?.height != controlKey.currentContext?.size?.height) {
|
||||||
debugPrint('Found some text that unexpectedly renders at different heights.');
|
debugPrint('Found some text that unexpectedly renders at different heights.');
|
||||||
debugPrint('Text: $_text');
|
debugPrint('Text: $_text');
|
||||||
|
@ -32,18 +32,18 @@ void main() {
|
|||||||
test('Image cache tracing', () async {
|
test('Image cache tracing', () async {
|
||||||
final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
|
final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
|
||||||
final TestImageStreamCompleter completer2 = TestImageStreamCompleter();
|
final TestImageStreamCompleter completer2 = TestImageStreamCompleter();
|
||||||
PaintingBinding.instance!.imageCache!.putIfAbsent(
|
PaintingBinding.instance.imageCache.putIfAbsent(
|
||||||
'Test',
|
'Test',
|
||||||
() => completer1,
|
() => completer1,
|
||||||
);
|
);
|
||||||
PaintingBinding.instance!.imageCache!.clear();
|
PaintingBinding.instance.imageCache.clear();
|
||||||
|
|
||||||
completer2.testSetImage(ImageInfo(image: await createTestImage()));
|
completer2.testSetImage(ImageInfo(image: await createTestImage()));
|
||||||
PaintingBinding.instance!.imageCache!.putIfAbsent(
|
PaintingBinding.instance.imageCache.putIfAbsent(
|
||||||
'Test2',
|
'Test2',
|
||||||
() => completer2,
|
() => completer2,
|
||||||
);
|
);
|
||||||
PaintingBinding.instance!.imageCache!.evict('Test2');
|
PaintingBinding.instance.imageCache.evict('Test2');
|
||||||
|
|
||||||
final Timeline timeline = await vmService.getVMTimeline();
|
final Timeline timeline = await vmService.getVMTimeline();
|
||||||
_expectTimelineEvents(
|
_expectTimelineEvents(
|
||||||
|
@ -18,12 +18,12 @@ class _LifecycleWatcherState extends State<LifecycleWatcher>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,6 @@ void main() {
|
|||||||
test('layers smoketest for rendering/custom_coordinate_systems.dart', () {
|
test('layers smoketest for rendering/custom_coordinate_systems.dart', () {
|
||||||
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
||||||
demo.main();
|
demo.main();
|
||||||
expect(SchedulerBinding.instance!.hasScheduledFrame, true);
|
expect(SchedulerBinding.instance.hasScheduledFrame, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ void main() {
|
|||||||
test('layers smoketest for rendering/flex_layout.dart', () {
|
test('layers smoketest for rendering/flex_layout.dart', () {
|
||||||
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
||||||
demo.main();
|
demo.main();
|
||||||
expect(SchedulerBinding.instance!.hasScheduledFrame, true);
|
expect(SchedulerBinding.instance.hasScheduledFrame, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ void main() {
|
|||||||
test('layers smoketest for rendering/hello_world.dart', () {
|
test('layers smoketest for rendering/hello_world.dart', () {
|
||||||
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
||||||
demo.main();
|
demo.main();
|
||||||
expect(SchedulerBinding.instance!.hasScheduledFrame, true);
|
expect(SchedulerBinding.instance.hasScheduledFrame, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ void main() {
|
|||||||
test('layers smoketest for rendering/spinning_square.dart', () {
|
test('layers smoketest for rendering/spinning_square.dart', () {
|
||||||
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
||||||
demo.main();
|
demo.main();
|
||||||
expect(SchedulerBinding.instance!.hasScheduledFrame, true);
|
expect(SchedulerBinding.instance.hasScheduledFrame, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ void main() {
|
|||||||
test('layers smoketest for rendering/touch_input.dart', () {
|
test('layers smoketest for rendering/touch_input.dart', () {
|
||||||
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
FlutterError.onError = (FlutterErrorDetails details) { throw details.exception; };
|
||||||
demo.main();
|
demo.main();
|
||||||
expect(SchedulerBinding.instance!.hasScheduledFrame, true);
|
expect(SchedulerBinding.instance.hasScheduledFrame, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ void attachWidgetTreeToRenderTree(RenderProxyBox container) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).attachToRenderTree(WidgetsBinding.instance!.buildOwner!, element);
|
).attachToRenderTree(WidgetsBinding.instance.buildOwner!, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
Duration? timeBase;
|
Duration? timeBase;
|
||||||
@ -86,7 +86,7 @@ void rotate(Duration timeStamp) {
|
|||||||
transformBox.setIdentity();
|
transformBox.setIdentity();
|
||||||
transformBox.rotateZ(delta);
|
transformBox.rotateZ(delta);
|
||||||
|
|
||||||
WidgetsBinding.instance!.buildOwner!.buildScope(element!);
|
WidgetsBinding.instance.buildOwner!.buildScope(element!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -567,7 +567,7 @@ class AnimationController extends Animation<double>
|
|||||||
|
|
||||||
TickerFuture _animateToInternal(double target, { Duration? duration, Curve curve = Curves.linear }) {
|
TickerFuture _animateToInternal(double target, { Duration? duration, Curve curve = Curves.linear }) {
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
if (SemanticsBinding.instance!.disableAnimations) {
|
if (SemanticsBinding.instance.disableAnimations) {
|
||||||
switch (animationBehavior) {
|
switch (animationBehavior) {
|
||||||
case AnimationBehavior.normal:
|
case AnimationBehavior.normal:
|
||||||
// Since the framework cannot handle zero duration animations, we run it at 5% of the 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<double>
|
|||||||
: upperBound + _kFlingTolerance.distance;
|
: upperBound + _kFlingTolerance.distance;
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior;
|
final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior;
|
||||||
if (SemanticsBinding.instance!.disableAnimations) {
|
if (SemanticsBinding.instance.disableAnimations) {
|
||||||
switch (behavior) {
|
switch (behavior) {
|
||||||
case AnimationBehavior.normal:
|
case AnimationBehavior.normal:
|
||||||
// TODO(jonahwilliams): determine a better process for setting velocity.
|
// TODO(jonahwilliams): determine a better process for setting velocity.
|
||||||
|
@ -315,7 +315,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
|
|||||||
// because _ContextMenuRoute renders its first frame offscreen.
|
// because _ContextMenuRoute renders its first frame offscreen.
|
||||||
// Otherwise there would be a visible flash when nothing is rendered for
|
// Otherwise there would be a visible flash when nothing is rendered for
|
||||||
// one frame.
|
// one frame.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_lastOverlayEntry?.remove();
|
_lastOverlayEntry?.remove();
|
||||||
_lastOverlayEntry = null;
|
_lastOverlayEntry = null;
|
||||||
_openController.reset();
|
_openController.reset();
|
||||||
@ -742,7 +742,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
|
|||||||
|
|
||||||
// Render one frame offstage in the final position so that we can take
|
// Render one frame offstage in the final position so that we can take
|
||||||
// measurements of its layout and then animate to them.
|
// measurements of its layout and then animate to them.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_updateTweenRects();
|
_updateTweenRects();
|
||||||
_internalOffstage = false;
|
_internalOffstage = false;
|
||||||
_setOffstageInternally();
|
_setOffstageInternally();
|
||||||
|
@ -585,7 +585,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
|||||||
minuteController = FixedExtentScrollController(initialItem: initialDateTime.minute ~/ widget.minuteInterval);
|
minuteController = FixedExtentScrollController(initialItem: initialDateTime.minute ~/ widget.minuteInterval);
|
||||||
dateController = FixedExtentScrollController(initialItem: 0);
|
dateController = FixedExtentScrollController(initialItem: 0);
|
||||||
|
|
||||||
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSystemFontsChange () {
|
void _handleSystemFontsChange () {
|
||||||
@ -604,7 +604,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
|||||||
minuteController.dispose();
|
minuteController.dispose();
|
||||||
meridiemController.dispose();
|
meridiemController.dispose();
|
||||||
|
|
||||||
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +930,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
|||||||
|
|
||||||
void _scrollToDate(DateTime newDate, DateTime fromDate) {
|
void _scrollToDate(DateTime newDate, DateTime fromDate) {
|
||||||
assert(newDate != null);
|
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) {
|
if (fromDate.year != newDate.year || fromDate.month != newDate.month || fromDate.day != newDate.day) {
|
||||||
_animateColumnControllerToItem(dateController, selectedDayFromInitial);
|
_animateColumnControllerToItem(dateController, selectedDayFromInitial);
|
||||||
}
|
}
|
||||||
@ -1104,7 +1104,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
|||||||
monthController = FixedExtentScrollController(initialItem: selectedMonth - 1);
|
monthController = FixedExtentScrollController(initialItem: selectedMonth - 1);
|
||||||
yearController = FixedExtentScrollController(initialItem: selectedYear);
|
yearController = FixedExtentScrollController(initialItem: selectedYear);
|
||||||
|
|
||||||
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSystemFontsChange() {
|
void _handleSystemFontsChange() {
|
||||||
@ -1120,7 +1120,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
|||||||
monthController.dispose();
|
monthController.dispose();
|
||||||
yearController.dispose();
|
yearController.dispose();
|
||||||
|
|
||||||
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,7 +1326,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
|||||||
|
|
||||||
void _scrollToDate(DateTime newDate) {
|
void _scrollToDate(DateTime newDate) {
|
||||||
assert(newDate != null);
|
assert(newDate != null);
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
|
||||||
if (selectedYear != newDate.year) {
|
if (selectedYear != newDate.year) {
|
||||||
_animateColumnControllerToItem(yearController, newDate.year);
|
_animateColumnControllerToItem(yearController, newDate.year);
|
||||||
}
|
}
|
||||||
@ -1608,7 +1608,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
|||||||
if (widget.mode != CupertinoTimerPickerMode.hm)
|
if (widget.mode != CupertinoTimerPickerMode.hm)
|
||||||
selectedSecond = widget.initialTimerDuration.inSeconds % 60;
|
selectedSecond = widget.initialTimerDuration.inSeconds % 60;
|
||||||
|
|
||||||
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSystemFontsChange() {
|
void _handleSystemFontsChange() {
|
||||||
@ -1621,7 +1621,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
|
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,10 +506,10 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
|
|||||||
nextState = RefreshIndicatorMode.done;
|
nextState = RefreshIndicatorMode.done;
|
||||||
// Either schedule the RenderSliver to re-layout on the next frame
|
// Either schedule the RenderSliver to re-layout on the next frame
|
||||||
// when not currently in a frame or schedule it on the next frame.
|
// when not currently in a frame or schedule it on the next frame.
|
||||||
if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
|
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) {
|
||||||
setState(() => hasSliverLayoutExtent = false);
|
setState(() => hasSliverLayoutExtent = false);
|
||||||
} else {
|
} else {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
|
||||||
setState(() => hasSliverLayoutExtent = false);
|
setState(() => hasSliverLayoutExtent = false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -535,7 +535,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
|
|||||||
// Call onRefresh after this frame finished since the function is
|
// Call onRefresh after this frame finished since the function is
|
||||||
// user supplied and we're always here in the middle of the sliver's
|
// user supplied and we're always here in the middle of the sliver's
|
||||||
// performLayout.
|
// performLayout.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
|
||||||
refreshTask = widget.onRefresh!()..whenComplete(() {
|
refreshTask = widget.onRefresh!()..whenComplete(() {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() => refreshTask = null);
|
setState(() => refreshTask = null);
|
||||||
|
@ -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
|
`hashValues` (and maybe one day `hashList` and `lerpDouble`), which
|
||||||
are all intended to be moved out of `dart:ui` and into `dart:core`.
|
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:
|
See also:
|
||||||
|
|
||||||
* https://github.com/dart-lang/sdk/issues/27791 (`VoidCallback`)
|
* https://github.com/dart-lang/sdk/issues/27791 (`VoidCallback`)
|
||||||
|
@ -14,10 +14,14 @@ import 'assertions.dart';
|
|||||||
import 'basic_types.dart';
|
import 'basic_types.dart';
|
||||||
import 'constants.dart';
|
import 'constants.dart';
|
||||||
import 'debug.dart';
|
import 'debug.dart';
|
||||||
|
import 'diagnostics.dart';
|
||||||
import 'object.dart';
|
import 'object.dart';
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
import 'print.dart';
|
import 'print.dart';
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// mixin BarBinding on BindingBase { }
|
||||||
|
|
||||||
/// Signature for service extensions.
|
/// Signature for service extensions.
|
||||||
///
|
///
|
||||||
/// The returned map must not contain the keys "type" or "method", as
|
/// 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.
|
/// "method" key will be set to the full name of the method.
|
||||||
typedef ServiceExtensionCallback = Future<Map<String, dynamic>> Function(Map<String, String> parameters);
|
typedef ServiceExtensionCallback = Future<Map<String, dynamic>> Function(Map<String, String> parameters);
|
||||||
|
|
||||||
/// Base class for mixins that provide singleton services (also known as
|
/// Base class for mixins that provide singleton services.
|
||||||
/// "bindings").
|
|
||||||
///
|
///
|
||||||
/// To use this class in an `on` clause of a mixin, inherit from it and implement
|
/// The Flutter engine ([dart:ui]) exposes some low-level services,
|
||||||
/// [initInstances()]. The mixin is guaranteed to only be constructed once in
|
/// but these are typically not suitable for direct use, for example
|
||||||
/// the lifetime of the app (more precisely, it will assert if constructed twice
|
/// because they only provide a single callback which an application
|
||||||
/// in checked mode).
|
/// may wish to multiplex to allow multiple listeners.
|
||||||
///
|
///
|
||||||
/// The top-most layer used to write the application will have a concrete class
|
/// Bindings provide the glue between these low-level APIs and the
|
||||||
/// that inherits from [BindingBase] and uses all the various [BindingBase]
|
/// higher-level framework APIs. They _bind_ the two together, whence
|
||||||
/// mixins (such as [ServicesBinding]). For example, the Widgets library in
|
/// the name.
|
||||||
/// Flutter introduces a binding called [WidgetsFlutterBinding]. The relevant
|
///
|
||||||
/// library defines how to create the binding. It could be implied (for example,
|
/// ## Implementing a binding mixin
|
||||||
/// [WidgetsFlutterBinding] is automatically started from [runApp]), or the
|
///
|
||||||
/// application might be required to explicitly call the constructor.
|
/// 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 {
|
abstract class BindingBase {
|
||||||
/// Default abstract constructor for bindings.
|
/// Default abstract constructor for bindings.
|
||||||
///
|
///
|
||||||
@ -51,6 +135,10 @@ abstract class BindingBase {
|
|||||||
/// observatory service extensions, if any.
|
/// observatory service extensions, if any.
|
||||||
BindingBase() {
|
BindingBase() {
|
||||||
developer.Timeline.startSync('Framework initialization');
|
developer.Timeline.startSync('Framework initialization');
|
||||||
|
assert(() {
|
||||||
|
_debugConstructed = true;
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
|
||||||
assert(!_debugInitialized);
|
assert(!_debugInitialized);
|
||||||
initInstances();
|
initInstances();
|
||||||
@ -65,6 +153,7 @@ abstract class BindingBase {
|
|||||||
developer.Timeline.finishSync();
|
developer.Timeline.finishSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _debugConstructed = false;
|
||||||
static bool _debugInitialized = false;
|
static bool _debugInitialized = false;
|
||||||
static bool _debugServiceExtensionsRegistered = false;
|
static bool _debugServiceExtensionsRegistered = false;
|
||||||
|
|
||||||
@ -131,10 +220,39 @@ abstract class BindingBase {
|
|||||||
/// the platform and otherwise configure their services. Subclasses must call
|
/// the platform and otherwise configure their services. Subclasses must call
|
||||||
/// "super.initInstances()".
|
/// "super.initInstances()".
|
||||||
///
|
///
|
||||||
/// By convention, if the service is to be provided as a singleton, it should
|
/// The binding is not fully initialized when this method runs (for
|
||||||
/// be exposed as `MixinClassName.instance`, a static getter that returns
|
/// 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
|
/// `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
|
@protected
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void initInstances() {
|
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 extends BindingBase>(T? instance) {
|
||||||
|
assert(() {
|
||||||
|
if (!_debugInitialized && instance == null) {
|
||||||
|
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||||
|
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(<DiagnosticsNode>[
|
||||||
|
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(<DiagnosticsNode>[
|
||||||
|
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(<DiagnosticsNode>[
|
||||||
|
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(<DiagnosticsNode>[
|
||||||
|
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
|
/// Called when the binding is initialized, to register service
|
||||||
/// extensions.
|
/// extensions.
|
||||||
///
|
///
|
||||||
@ -555,7 +767,7 @@ abstract class BindingBase {
|
|||||||
/// available in debug and profile mode.
|
/// available in debug and profile mode.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// void myRegistrationFunction() {
|
/// void myOtherRegistrationFunction() {
|
||||||
/// // kReleaseMode is defined in the 'flutter/foundation.dart' package.
|
/// // kReleaseMode is defined in the 'flutter/foundation.dart' package.
|
||||||
/// if (!kReleaseMode) {
|
/// if (!kReleaseMode) {
|
||||||
/// // Register your service extension here.
|
/// // Register your service extension here.
|
||||||
|
@ -73,7 +73,7 @@ class _Resampler {
|
|||||||
// Add `event` for resampling or dispatch it directly if
|
// Add `event` for resampling or dispatch it directly if
|
||||||
// not a touch event.
|
// not a touch event.
|
||||||
void addOrDispatch(PointerEvent event) {
|
void addOrDispatch(PointerEvent event) {
|
||||||
final SchedulerBinding? scheduler = SchedulerBinding.instance;
|
final SchedulerBinding scheduler = SchedulerBinding.instance;
|
||||||
assert(scheduler != null);
|
assert(scheduler != null);
|
||||||
// Add touch event to resampler or dispatch pointer event directly.
|
// Add touch event to resampler or dispatch pointer event directly.
|
||||||
if (event.kind == PointerDeviceKind.touch) {
|
if (event.kind == PointerDeviceKind.touch) {
|
||||||
@ -94,9 +94,10 @@ class _Resampler {
|
|||||||
//
|
//
|
||||||
// The `samplingOffset` is relative to the current frame time, which
|
// The `samplingOffset` is relative to the current frame time, which
|
||||||
// can be in the past when we're not actively resampling.
|
// can be in the past when we're not actively resampling.
|
||||||
|
//
|
||||||
// The `samplingClock` is the clock used to determine frame time age.
|
// The `samplingClock` is the clock used to determine frame time age.
|
||||||
void sample(Duration samplingOffset, SamplingClock clock) {
|
void sample(Duration samplingOffset, SamplingClock clock) {
|
||||||
final SchedulerBinding? scheduler = SchedulerBinding.instance;
|
final SchedulerBinding scheduler = SchedulerBinding.instance;
|
||||||
assert(scheduler != null);
|
assert(scheduler != null);
|
||||||
|
|
||||||
// Initialize `_frameTime` if needed. This will be used for periodic
|
// 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
|
// Add a post frame callback as this avoids producing unnecessary
|
||||||
// frames but ensures that sampling phase is adjusted to frame
|
// frames but ensures that sampling phase is adjusted to frame
|
||||||
// time when frames are produced.
|
// time when frames are produced.
|
||||||
scheduler?.addPostFrameCallback((_) {
|
scheduler.addPostFrameCallback((_) {
|
||||||
_frameCallbackScheduled = false;
|
_frameCallbackScheduled = false;
|
||||||
// We use `currentSystemFrameTimeStamp` here as it's critical that
|
// We use `currentSystemFrameTimeStamp` here as it's critical that
|
||||||
// sample time is in the same clock as the event time stamps, and
|
// 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;
|
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
|
@override
|
||||||
void unlocked() {
|
void unlocked() {
|
||||||
super.unlocked();
|
super.unlocked();
|
||||||
_flushPointerEventQueue();
|
_flushPointerEventQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The singleton instance of this object.
|
|
||||||
static GestureBinding? get instance => _instance;
|
|
||||||
static GestureBinding? _instance;
|
|
||||||
|
|
||||||
final Queue<PointerEvent> _pendingPointerEvents = Queue<PointerEvent>();
|
final Queue<PointerEvent> _pendingPointerEvents = Queue<PointerEvent>();
|
||||||
|
|
||||||
void _handlePointerDataPacket(ui.PointerDataPacket packet) {
|
void _handlePointerDataPacket(ui.PointerDataPacket packet) {
|
||||||
|
@ -231,8 +231,8 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer {
|
|||||||
assert(!_pointers!.containsKey(event.pointer));
|
assert(!_pointers!.containsKey(event.pointer));
|
||||||
final MultiDragPointerState state = createNewPointerState(event);
|
final MultiDragPointerState state = createNewPointerState(event);
|
||||||
_pointers![event.pointer] = state;
|
_pointers![event.pointer] = state;
|
||||||
GestureBinding.instance!.pointerRouter.addRoute(event.pointer, _handleEvent);
|
GestureBinding.instance.pointerRouter.addRoute(event.pointer, _handleEvent);
|
||||||
state._setArenaEntry(GestureBinding.instance!.gestureArena.add(event.pointer, this));
|
state._setArenaEntry(GestureBinding.instance.gestureArena.add(event.pointer, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subclasses should override this method to create per-pointer state
|
/// Subclasses should override this method to create per-pointer state
|
||||||
@ -312,7 +312,7 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(_pointers!.containsKey(pointer));
|
assert(_pointers!.containsKey(pointer));
|
||||||
GestureBinding.instance!.pointerRouter.removeRoute(pointer, _handleEvent);
|
GestureBinding.instance.pointerRouter.removeRoute(pointer, _handleEvent);
|
||||||
_pointers!.remove(pointer)!.dispose();
|
_pointers!.remove(pointer)!.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +79,14 @@ class _TapTracker {
|
|||||||
void startTrackingPointer(PointerRoute route, Matrix4? transform) {
|
void startTrackingPointer(PointerRoute route, Matrix4? transform) {
|
||||||
if (!_isTrackingPointer) {
|
if (!_isTrackingPointer) {
|
||||||
_isTrackingPointer = true;
|
_isTrackingPointer = true;
|
||||||
GestureBinding.instance!.pointerRouter.addRoute(pointer, route, transform);
|
GestureBinding.instance.pointerRouter.addRoute(pointer, route, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopTrackingPointer(PointerRoute route) {
|
void stopTrackingPointer(PointerRoute route) {
|
||||||
if (_isTrackingPointer) {
|
if (_isTrackingPointer) {
|
||||||
_isTrackingPointer = false;
|
_isTrackingPointer = false;
|
||||||
GestureBinding.instance!.pointerRouter.removeRoute(pointer, route);
|
GestureBinding.instance.pointerRouter.removeRoute(pointer, route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
|
|||||||
_stopDoubleTapTimer();
|
_stopDoubleTapTimer();
|
||||||
final _TapTracker tracker = _TapTracker(
|
final _TapTracker tracker = _TapTracker(
|
||||||
event: event,
|
event: event,
|
||||||
entry: GestureBinding.instance!.gestureArena.add(event.pointer, this),
|
entry: GestureBinding.instance.gestureArena.add(event.pointer, this),
|
||||||
doubleTapMinTime: kDoubleTapMinTime,
|
doubleTapMinTime: kDoubleTapMinTime,
|
||||||
);
|
);
|
||||||
_trackers[event.pointer] = tracker;
|
_trackers[event.pointer] = tracker;
|
||||||
@ -311,14 +311,14 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
|
|||||||
final _TapTracker tracker = _firstTap!;
|
final _TapTracker tracker = _firstTap!;
|
||||||
_firstTap = null;
|
_firstTap = null;
|
||||||
_reject(tracker);
|
_reject(tracker);
|
||||||
GestureBinding.instance!.gestureArena.release(tracker.pointer);
|
GestureBinding.instance.gestureArena.release(tracker.pointer);
|
||||||
}
|
}
|
||||||
_clearTrackers();
|
_clearTrackers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _registerFirstTap(_TapTracker tracker) {
|
void _registerFirstTap(_TapTracker tracker) {
|
||||||
_startDoubleTapTimer();
|
_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
|
// Note, order is important below in order for the clear -> reject logic to
|
||||||
// work properly.
|
// work properly.
|
||||||
_freezeTracker(tracker);
|
_freezeTracker(tracker);
|
||||||
@ -383,7 +383,7 @@ class _TapGesture extends _TapTracker {
|
|||||||
}) : _lastPosition = OffsetPair.fromEventPosition(event),
|
}) : _lastPosition = OffsetPair.fromEventPosition(event),
|
||||||
super(
|
super(
|
||||||
event: event as PointerDownEvent,
|
event: event as PointerDownEvent,
|
||||||
entry: GestureBinding.instance!.gestureArena.add(event.pointer, gestureRecognizer),
|
entry: GestureBinding.instance.gestureArena.add(event.pointer, gestureRecognizer),
|
||||||
doubleTapMinTime: kDoubleTapMinTime,
|
doubleTapMinTime: kDoubleTapMinTime,
|
||||||
) {
|
) {
|
||||||
startTrackingPointer(handleEvent, event.transform);
|
startTrackingPointer(handleEvent, event.transform);
|
||||||
|
@ -30,7 +30,7 @@ bool _isSameEvent(PointerSignalEvent event1, PointerSignalEvent event2) {
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// void handleSignalEvent(PointerSignalEvent event) {
|
/// void handleSignalEvent(PointerSignalEvent event) {
|
||||||
/// GestureBinding.instance!.pointerSignalResolver.register(event, (PointerSignalEvent event) {
|
/// GestureBinding.instance.pointerSignalResolver.register(event, (PointerSignalEvent event) {
|
||||||
/// // handle the event...
|
/// // handle the event...
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
@ -96,7 +96,7 @@ bool _isSameEvent(PointerSignalEvent event1, PointerSignalEvent event2) {
|
|||||||
/// child: Listener(
|
/// child: Listener(
|
||||||
/// onPointerSignal: (PointerSignalEvent event) {
|
/// onPointerSignal: (PointerSignalEvent event) {
|
||||||
/// if (widget.useResolver) {
|
/// if (widget.useResolver) {
|
||||||
/// GestureBinding.instance!.pointerSignalResolver.register(event, (PointerSignalEvent event) {
|
/// GestureBinding.instance.pointerSignalResolver.register(event, (PointerSignalEvent event) {
|
||||||
/// rotateColor();
|
/// rotateColor();
|
||||||
/// });
|
/// });
|
||||||
/// } else {
|
/// } else {
|
||||||
|
@ -317,7 +317,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
resolve(GestureDisposition.rejected);
|
resolve(GestureDisposition.rejected);
|
||||||
for (final int pointer in _trackedPointers)
|
for (final int pointer in _trackedPointers)
|
||||||
GestureBinding.instance!.pointerRouter.removeRoute(pointer, handleEvent);
|
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
|
||||||
_trackedPointers.clear();
|
_trackedPointers.clear();
|
||||||
assert(_entries.isEmpty);
|
assert(_entries.isEmpty);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@ -347,7 +347,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
|
|||||||
GestureArenaEntry _addPointerToArena(int pointer) {
|
GestureArenaEntry _addPointerToArena(int pointer) {
|
||||||
if (_team != null)
|
if (_team != null)
|
||||||
return _team!.add(pointer, this);
|
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.
|
/// 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].
|
/// This is called by [OneSequenceGestureRecognizer.addAllowedPointer].
|
||||||
@protected
|
@protected
|
||||||
void startTrackingPointer(int pointer, [Matrix4? transform]) {
|
void startTrackingPointer(int pointer, [Matrix4? transform]) {
|
||||||
GestureBinding.instance!.pointerRouter.addRoute(pointer, handleEvent, transform);
|
GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform);
|
||||||
_trackedPointers.add(pointer);
|
_trackedPointers.add(pointer);
|
||||||
assert(!_entries.containsValue(pointer));
|
assert(!_entries.containsValue(pointer));
|
||||||
_entries[pointer] = _addPointerToArena(pointer);
|
_entries[pointer] = _addPointerToArena(pointer);
|
||||||
@ -381,7 +381,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
|
|||||||
@protected
|
@protected
|
||||||
void stopTrackingPointer(int pointer) {
|
void stopTrackingPointer(int pointer) {
|
||||||
if (_trackedPointers.contains(pointer)) {
|
if (_trackedPointers.contains(pointer)) {
|
||||||
GestureBinding.instance!.pointerRouter.removeRoute(pointer, handleEvent);
|
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
|
||||||
_trackedPointers.remove(pointer);
|
_trackedPointers.remove(pointer);
|
||||||
if (_trackedPointers.isEmpty)
|
if (_trackedPointers.isEmpty)
|
||||||
didStopTrackingLastPointer(pointer);
|
didStopTrackingLastPointer(pointer);
|
||||||
|
@ -61,7 +61,7 @@ class _CombiningGestureArenaMember extends GestureArenaMember {
|
|||||||
assert(!_resolved);
|
assert(!_resolved);
|
||||||
assert(_pointer == pointer);
|
assert(_pointer == pointer);
|
||||||
_members.add(member);
|
_members.add(member);
|
||||||
_entry ??= GestureBinding.instance!.gestureArena.add(pointer, this);
|
_entry ??= GestureBinding.instance.gestureArena.add(pointer, this);
|
||||||
return _CombiningGestureArenaEntry(this, member);
|
return _CombiningGestureArenaEntry(this, member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
|
|||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
final List<LicenseParagraph> paragraphs =
|
final List<LicenseParagraph> paragraphs =
|
||||||
await SchedulerBinding.instance!.scheduleTask<List<LicenseParagraph>>(
|
await SchedulerBinding.instance.scheduleTask<List<LicenseParagraph>>(
|
||||||
license.paragraphs.toList,
|
license.paragraphs.toList,
|
||||||
Priority.animation,
|
Priority.animation,
|
||||||
debugLabel: 'License',
|
debugLabel: 'License',
|
||||||
@ -1507,15 +1507,13 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void openDetailPage(Object arguments) {
|
void openDetailPage(Object arguments) {
|
||||||
SchedulerBinding.instance!
|
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
||||||
.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
|
||||||
_MasterDetailFlow.of(context)!.openDetailPage(arguments);
|
_MasterDetailFlow.of(context)!.openDetailPage(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setInitialDetailPage(Object arguments) {
|
void setInitialDetailPage(Object arguments) {
|
||||||
SchedulerBinding.instance!
|
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
||||||
.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
|
||||||
_MasterDetailFlow.of(context)!.setInitialDetailPage(arguments);
|
_MasterDetailFlow.of(context)!.setInitialDetailPage(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final bool highlight = AutocompleteHighlightedOption.of(context) == index;
|
final bool highlight = AutocompleteHighlightedOption.of(context) == index;
|
||||||
if (highlight) {
|
if (highlight) {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
Scrollable.ensureVisible(context, alignment: 0.5);
|
Scrollable.ensureVisible(context, alignment: 0.5);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -533,7 +533,7 @@ class _MonthPickerState extends State<_MonthPicker> {
|
|||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.initialMonth != oldWidget.initialMonth && widget.initialMonth != _currentMonth) {
|
if (widget.initialMonth != oldWidget.initialMonth && widget.initialMonth != _currentMonth) {
|
||||||
// We can't interrupt this widget build with a scroll, so do it next frame
|
// 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),
|
(Duration timeStamp) => _showMonth(widget.initialMonth, jump: true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1237,16 +1237,16 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
focusNode!.addListener(_handleFocusChanged);
|
focusNode!.addListener(_handleFocusChanged);
|
||||||
final FocusManager focusManager = WidgetsBinding.instance!.focusManager;
|
final FocusManager focusManager = WidgetsBinding.instance.focusManager;
|
||||||
_focusHighlightMode = focusManager.highlightMode;
|
_focusHighlightMode = focusManager.highlightMode;
|
||||||
focusManager.addHighlightModeListener(_handleFocusHighlightModeChange);
|
focusManager.addHighlightModeListener(_handleFocusHighlightModeChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_removeDropdownRoute();
|
_removeDropdownRoute();
|
||||||
WidgetsBinding.instance!.focusManager.removeHighlightModeListener(_handleFocusHighlightModeChange);
|
WidgetsBinding.instance.focusManager.removeHighlightModeListener(_handleFocusHighlightModeChange);
|
||||||
focusNode!.removeListener(_handleFocusChanged);
|
focusNode!.removeListener(_handleFocusChanged);
|
||||||
_internalNode?.dispose();
|
_internalNode?.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -161,7 +161,7 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
|
|||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.initialDate != oldWidget.initialDate) {
|
if (widget.initialDate != oldWidget.initialDate) {
|
||||||
// Can't update the form field in the middle of a build, so do it next frame
|
// 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(() {
|
setState(() {
|
||||||
_selectedDate = widget.initialDate;
|
_selectedDate = widget.initialDate;
|
||||||
_updateValueForSelectedDate();
|
_updateValueForSelectedDate();
|
||||||
|
@ -833,7 +833,7 @@ class _DialPainter extends CustomPainter {
|
|||||||
required this.theta,
|
required this.theta,
|
||||||
required this.textDirection,
|
required this.textDirection,
|
||||||
required this.selectedValue,
|
required this.selectedValue,
|
||||||
}) : super(repaint: PaintingBinding.instance!.systemFonts);
|
}) : super(repaint: PaintingBinding.instance.systemFonts);
|
||||||
|
|
||||||
final List<_TappableLabel> primaryLabels;
|
final List<_TappableLabel> primaryLabels;
|
||||||
final List<_TappableLabel> secondaryLabels;
|
final List<_TappableLabel> secondaryLabels;
|
||||||
|
@ -269,7 +269,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_mouseIsConnected = RendererBinding.instance!.mouseTracker.mouseIsConnected;
|
_mouseIsConnected = RendererBinding.instance.mouseTracker.mouseIsConnected;
|
||||||
_controller = AnimationController(
|
_controller = AnimationController(
|
||||||
duration: _fadeInDuration,
|
duration: _fadeInDuration,
|
||||||
reverseDuration: _fadeOutDuration,
|
reverseDuration: _fadeOutDuration,
|
||||||
@ -277,10 +277,10 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
)
|
)
|
||||||
..addStatusListener(_handleStatusChanged);
|
..addStatusListener(_handleStatusChanged);
|
||||||
// Listen to see when a mouse is added.
|
// 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
|
// Listen to global pointer events so that we can hide a tooltip immediately
|
||||||
// if some other control is clicked on.
|
// if some other control is clicked on.
|
||||||
GestureBinding.instance!.pointerRouter.addGlobalRoute(_handlePointerEvent);
|
GestureBinding.instance.pointerRouter.addGlobalRoute(_handlePointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://material.io/components/tooltips#specs
|
// https://material.io/components/tooltips#specs
|
||||||
@ -325,7 +325,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final bool mouseIsConnected = RendererBinding.instance!.mouseTracker.mouseIsConnected;
|
final bool mouseIsConnected = RendererBinding.instance.mouseTracker.mouseIsConnected;
|
||||||
if (mouseIsConnected != _mouseIsConnected) {
|
if (mouseIsConnected != _mouseIsConnected) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_mouseIsConnected = mouseIsConnected;
|
_mouseIsConnected = mouseIsConnected;
|
||||||
@ -456,8 +456,8 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handlePointerEvent);
|
GestureBinding.instance.pointerRouter.removeGlobalRoute(_handlePointerEvent);
|
||||||
RendererBinding.instance!.mouseTracker.removeListener(_handleMouseTrackerChange);
|
RendererBinding.instance.mouseTracker.removeListener(_handleMouseTrackerChange);
|
||||||
_removeEntry();
|
_removeEntry();
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -118,7 +118,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
|
|||||||
// have had a chance to track the key in the cache at all.
|
// have had a chance to track the key in the cache at all.
|
||||||
// Schedule a microtask to give the cache a chance to add the key.
|
// Schedule a microtask to give the cache a chance to add the key.
|
||||||
scheduleMicrotask(() {
|
scheduleMicrotask(() {
|
||||||
PaintingBinding.instance!.imageCache!.evict(key);
|
PaintingBinding.instance.imageCache.evict(key);
|
||||||
});
|
});
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
import 'dart:typed_data' show Uint8List;
|
import 'dart:typed_data' show Uint8List;
|
||||||
import 'dart:ui' as ui show instantiateImageCodec, Codec;
|
import 'dart:ui' as ui show instantiateImageCodec, Codec;
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -26,7 +25,11 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The current [PaintingBinding], if one has been created.
|
/// The current [PaintingBinding], if one has been created.
|
||||||
static PaintingBinding? 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 PaintingBinding get instance => BindingBase.checkInstance(_instance);
|
||||||
static PaintingBinding? _instance;
|
static PaintingBinding? _instance;
|
||||||
|
|
||||||
/// [ShaderWarmUp] instance to be executed during [initInstances].
|
/// [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]
|
/// The image cache is created during startup by the [createImageCache]
|
||||||
/// method.
|
/// method.
|
||||||
ImageCache? get imageCache => _imageCache;
|
ImageCache get imageCache => _imageCache;
|
||||||
ImageCache? _imageCache;
|
late ImageCache _imageCache;
|
||||||
|
|
||||||
/// Creates the [ImageCache] singleton (accessible via [imageCache]).
|
/// Creates the [ImageCache] singleton (accessible via [imageCache]).
|
||||||
///
|
///
|
||||||
@ -114,14 +117,14 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
|
|||||||
@override
|
@override
|
||||||
void evict(String asset) {
|
void evict(String asset) {
|
||||||
super.evict(asset);
|
super.evict(asset);
|
||||||
imageCache!.clear();
|
imageCache.clear();
|
||||||
imageCache!.clearLiveImages();
|
imageCache.clearLiveImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void handleMemoryPressure() {
|
void handleMemoryPressure() {
|
||||||
super.handleMemoryPressure();
|
super.handleMemoryPressure();
|
||||||
imageCache?.clear();
|
imageCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listenable that notifies when the available fonts on the system have
|
/// 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
|
/// The image cache is created during startup by the [PaintingBinding]'s
|
||||||
/// [PaintingBinding.createImageCache] method.
|
/// [PaintingBinding.createImageCache] method.
|
||||||
ImageCache? get imageCache => PaintingBinding.instance!.imageCache;
|
ImageCache get imageCache => PaintingBinding.instance.imageCache;
|
||||||
|
@ -539,7 +539,7 @@ void paintImage({
|
|||||||
_pendingImageSizeInfo[sizeInfo.source!] = sizeInfo;
|
_pendingImageSizeInfo[sizeInfo.source!] = sizeInfo;
|
||||||
}
|
}
|
||||||
debugOnPaintImage?.call(sizeInfo);
|
debugOnPaintImage?.call(sizeInfo);
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
_lastFrameImageSizeInfo = _pendingImageSizeInfo.values.toSet();
|
_lastFrameImageSizeInfo = _pendingImageSizeInfo.values.toSet();
|
||||||
if (_pendingImageSizeInfo.isEmpty) {
|
if (_pendingImageSizeInfo.isEmpty) {
|
||||||
return;
|
return;
|
||||||
|
@ -622,7 +622,7 @@ abstract class _CachedImageBase {
|
|||||||
assert(handle != null);
|
assert(handle != null);
|
||||||
// Give any interested parties a chance to listen to the stream before we
|
// Give any interested parties a chance to listen to the stream before we
|
||||||
// potentially dispose it.
|
// potentially dispose it.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
assert(handle != null);
|
assert(handle != null);
|
||||||
handle?.dispose();
|
handle?.dispose();
|
||||||
handle = null;
|
handle = null;
|
||||||
|
@ -21,7 +21,7 @@ import 'binding.dart';
|
|||||||
/// [PaintingBinding.instantiateImageCodec], and therefore can be mocked in
|
/// [PaintingBinding.instantiateImageCodec], and therefore can be mocked in
|
||||||
/// tests.
|
/// tests.
|
||||||
Future<ui.Image> decodeImageFromList(Uint8List bytes) async {
|
Future<ui.Image> 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();
|
final ui.FrameInfo frameInfo = await codec.getNextFrame();
|
||||||
return frameInfo.image;
|
return frameInfo.image;
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
_createErrorHandlerAndKey(
|
_createErrorHandlerAndKey(
|
||||||
configuration,
|
configuration,
|
||||||
(T key, ImageErrorListener innerHandleError) {
|
(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 {
|
(T? key, Object exception, StackTrace? stack) async {
|
||||||
if (handleError != null) {
|
if (handleError != null) {
|
||||||
@ -492,7 +492,7 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
// the image we want before getting to this method. We should avoid calling
|
// the image we want before getting to this method. We should avoid calling
|
||||||
// load again, but still update the image cache with LRU information.
|
// load again, but still update the image cache with LRU information.
|
||||||
if (stream.completer != null) {
|
if (stream.completer != null) {
|
||||||
final ImageStreamCompleter? completer = PaintingBinding.instance!.imageCache!.putIfAbsent(
|
final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent(
|
||||||
key,
|
key,
|
||||||
() => stream.completer!,
|
() => stream.completer!,
|
||||||
onError: handleError,
|
onError: handleError,
|
||||||
@ -500,9 +500,9 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
assert(identical(completer, stream.completer));
|
assert(identical(completer, stream.completer));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final ImageStreamCompleter? completer = PaintingBinding.instance!.imageCache!.putIfAbsent(
|
final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent(
|
||||||
key,
|
key,
|
||||||
() => load(key, PaintingBinding.instance!.instantiateImageCodec),
|
() => load(key, PaintingBinding.instance.instantiateImageCodec),
|
||||||
onError: handleError,
|
onError: handleError,
|
||||||
);
|
);
|
||||||
if (completer != null) {
|
if (completer != null) {
|
||||||
@ -557,7 +557,7 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
Future<bool> evict({ ImageCache? cache, ImageConfiguration configuration = ImageConfiguration.empty }) async {
|
Future<bool> evict({ ImageCache? cache, ImageConfiguration configuration = ImageConfiguration.empty }) async {
|
||||||
cache ??= imageCache;
|
cache ??= imageCache;
|
||||||
final T key = await obtainKey(configuration);
|
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
|
/// Converts an ImageProvider's settings plus an ImageConfiguration to a key
|
||||||
@ -674,11 +674,11 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
|
|||||||
try {
|
try {
|
||||||
data = await key.bundle.load(key.name);
|
data = await key.bundle.load(key.name);
|
||||||
} on FlutterError {
|
} on FlutterError {
|
||||||
PaintingBinding.instance!.imageCache!.evict(key);
|
PaintingBinding.instance.imageCache.evict(key);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
PaintingBinding.instance!.imageCache!.evict(key);
|
PaintingBinding.instance.imageCache.evict(key);
|
||||||
throw StateError('Unable to read data');
|
throw StateError('Unable to read data');
|
||||||
}
|
}
|
||||||
return decode(data.buffer.asUint8List());
|
return decode(data.buffer.asUint8List());
|
||||||
@ -891,7 +891,7 @@ class FileImage extends ImageProvider<FileImage> {
|
|||||||
|
|
||||||
if (bytes.lengthInBytes == 0) {
|
if (bytes.lengthInBytes == 0) {
|
||||||
// The file may become available later.
|
// 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.');
|
throw StateError('$file is empty and cannot be loaded as an image.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,7 +964,7 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_frameCallbackScheduled = true;
|
_frameCallbackScheduled = true;
|
||||||
SchedulerBinding.instance!.scheduleFrameCallback(_handleAppFrame);
|
SchedulerBinding.instance.scheduleFrameCallback(_handleAppFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _emitFrame(ImageInfo imageInfo) {
|
void _emitFrame(ImageInfo imageInfo) {
|
||||||
|
@ -49,7 +49,11 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The current [RendererBinding], if one has been created.
|
/// 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;
|
static RendererBinding? _instance;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -114,7 +118,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
registerServiceExtension(
|
registerServiceExtension(
|
||||||
name: 'debugDumpLayerTree',
|
name: 'debugDumpLayerTree',
|
||||||
callback: (Map<String, String> parameters) async {
|
callback: (Map<String, String> 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 <String, Object>{
|
return <String, Object>{
|
||||||
'data': data,
|
'data': data,
|
||||||
};
|
};
|
||||||
@ -128,7 +132,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
registerServiceExtension(
|
registerServiceExtension(
|
||||||
name: 'debugDumpRenderTree',
|
name: 'debugDumpRenderTree',
|
||||||
callback: (Map<String, String> parameters) async {
|
callback: (Map<String, String> parameters) async {
|
||||||
final String data = RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.';
|
final String data = RendererBinding.instance.renderView.toStringDeep();
|
||||||
return <String, Object>{
|
return <String, Object>{
|
||||||
'data': data,
|
'data': data,
|
||||||
};
|
};
|
||||||
@ -138,7 +142,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
registerServiceExtension(
|
registerServiceExtension(
|
||||||
name: 'debugDumpSemanticsTreeInTraversalOrder',
|
name: 'debugDumpSemanticsTreeInTraversalOrder',
|
||||||
callback: (Map<String, String> parameters) async {
|
callback: (Map<String, String> parameters) async {
|
||||||
final String data = RendererBinding.instance?.renderView.debugSemantics
|
final String data = RendererBinding.instance.renderView.debugSemantics
|
||||||
?.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversalOrder) ?? 'Semantics not collected.';
|
?.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversalOrder) ?? 'Semantics not collected.';
|
||||||
return <String, Object>{
|
return <String, Object>{
|
||||||
'data': data,
|
'data': data,
|
||||||
@ -149,7 +153,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
registerServiceExtension(
|
registerServiceExtension(
|
||||||
name: 'debugDumpSemanticsTreeInInverseHitTestOrder',
|
name: 'debugDumpSemanticsTreeInInverseHitTestOrder',
|
||||||
callback: (Map<String, String> parameters) async {
|
callback: (Map<String, String> parameters) async {
|
||||||
final String data = RendererBinding.instance?.renderView.debugSemantics
|
final String data = RendererBinding.instance.renderView.debugSemantics
|
||||||
?.toStringDeep(childOrder: DebugSemanticsDumpOrder.inverseHitTest) ?? 'Semantics not collected.';
|
?.toStringDeep(childOrder: DebugSemanticsDumpOrder.inverseHitTest) ?? 'Semantics not collected.';
|
||||||
return <String, Object>{
|
return <String, Object>{
|
||||||
'data': data,
|
'data': data,
|
||||||
@ -229,7 +233,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
/// Querying [PlatformDispatcher.platformBrightness].
|
/// Querying [PlatformDispatcher.platformBrightness].
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final Brightness brightness = WidgetsBinding.instance!.platformDispatcher.platformBrightness;
|
/// final Brightness brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
||||||
/// ```
|
/// ```
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
@ -338,7 +342,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
_debugMouseTrackerUpdateScheduled = true;
|
_debugMouseTrackerUpdateScheduled = true;
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
assert(_debugMouseTrackerUpdateScheduled);
|
assert(_debugMouseTrackerUpdateScheduled);
|
||||||
assert(() {
|
assert(() {
|
||||||
_debugMouseTrackerUpdateScheduled = false;
|
_debugMouseTrackerUpdateScheduled = false;
|
||||||
@ -501,19 +505,19 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||||||
child.markNeedsPaint();
|
child.markNeedsPaint();
|
||||||
child.visitChildren(visitor);
|
child.visitChildren(visitor);
|
||||||
};
|
};
|
||||||
instance?.renderView.visitChildren(visitor);
|
instance.renderView.visitChildren(visitor);
|
||||||
return endOfFrame;
|
return endOfFrame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints a textual representation of the entire render tree.
|
/// Prints a textual representation of the entire render tree.
|
||||||
void debugDumpRenderTree() {
|
void debugDumpRenderTree() {
|
||||||
debugPrint(RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.');
|
debugPrint(RendererBinding.instance.renderView.toStringDeep());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints a textual representation of the entire layer tree.
|
/// Prints a textual representation of the entire layer tree.
|
||||||
void debugDumpLayerTree() {
|
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.
|
/// 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
|
/// The order in which the children of a [SemanticsNode] will be printed is
|
||||||
/// controlled by the [childOrder] parameter.
|
/// controlled by the [childOrder] parameter.
|
||||||
void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) {
|
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
|
/// A concrete binding for applications that use the Rendering framework
|
||||||
/// directly. This is the glue that binds the framework to the Flutter engine.
|
/// 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
|
/// You would only use this binding if you are writing to the
|
||||||
/// rendering layer directly. If you are writing to a higher-level
|
/// rendering layer directly. If you are writing to a higher-level
|
||||||
/// library, such as the Flutter Widgets library, then you would use
|
/// 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 {
|
class RenderingFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, SemanticsBinding, PaintingBinding, RendererBinding {
|
||||||
/// Creates a binding for the rendering layer.
|
/// Creates a binding for the rendering layer.
|
||||||
///
|
///
|
||||||
@ -545,4 +560,18 @@ class RenderingFlutterBinding extends BindingBase with GestureBinding, Scheduler
|
|||||||
assert(renderView != null);
|
assert(renderView != null);
|
||||||
renderView.child = root;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3498,12 +3498,12 @@ mixin RelayoutWhenSystemFontsChangeMixin on RenderObject {
|
|||||||
@override
|
@override
|
||||||
void attach(covariant PipelineOwner owner) {
|
void attach(covariant PipelineOwner owner) {
|
||||||
super.attach(owner);
|
super.attach(owner);
|
||||||
PaintingBinding.instance!.systemFonts.addListener(systemFontsDidChange);
|
PaintingBinding.instance.systemFonts.addListener(systemFontsDidChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void detach() {
|
void detach() {
|
||||||
PaintingBinding.instance!.systemFonts.removeListener(systemFontsDidChange);
|
PaintingBinding.instance.systemFonts.removeListener(systemFontsDidChange);
|
||||||
super.detach();
|
super.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,12 +408,12 @@ class RenderUiKitView extends RenderBox {
|
|||||||
@override
|
@override
|
||||||
void attach(PipelineOwner owner) {
|
void attach(PipelineOwner owner) {
|
||||||
super.attach(owner);
|
super.attach(owner);
|
||||||
GestureBinding.instance!.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent);
|
GestureBinding.instance.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void detach() {
|
void detach() {
|
||||||
GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent);
|
GestureBinding.instance.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent);
|
||||||
_gestureRecognizer!.reset();
|
_gestureRecognizer!.reset();
|
||||||
super.detach();
|
super.detach();
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,18 @@ export 'dart:ui' show AppLifecycleState, VoidCallback, FrameTiming;
|
|||||||
/// Slows down animations by this factor to help in development.
|
/// Slows down animations by this factor to help in development.
|
||||||
double get timeDilation => _timeDilation;
|
double get timeDilation => _timeDilation;
|
||||||
double _timeDilation = 1.0;
|
double _timeDilation = 1.0;
|
||||||
/// Setting the time dilation automatically calls [SchedulerBinding.resetEpoch]
|
/// If the [SchedulerBinding] has been initialized, setting the time dilation
|
||||||
/// to ensure that time stamps seen by consumers of the scheduler binding are
|
/// automatically calls [SchedulerBinding.resetEpoch] to ensure that time stamps
|
||||||
/// always increasing.
|
/// seen by consumers of the scheduler binding are always increasing.
|
||||||
|
///
|
||||||
|
/// It is safe to set this before initializing the binding.
|
||||||
set timeDilation(double value) {
|
set timeDilation(double value) {
|
||||||
assert(value > 0.0);
|
assert(value > 0.0);
|
||||||
if (_timeDilation == value)
|
if (_timeDilation == value)
|
||||||
return;
|
return;
|
||||||
// We need to resetEpoch first so that we capture start of the epoch with the
|
// If the binding has been created, we need to resetEpoch first so that we
|
||||||
// current time dilation.
|
// capture start of the epoch with the current time dilation.
|
||||||
SchedulerBinding.instance?.resetEpoch();
|
SchedulerBinding._instance?.resetEpoch();
|
||||||
_timeDilation = value;
|
_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<TimingsCallback> _timingsCallbacks = <TimingsCallback>[];
|
final List<TimingsCallback> _timingsCallbacks = <TimingsCallback>[];
|
||||||
|
|
||||||
/// Add a [TimingsCallback] that receives [FrameTiming] sent from
|
/// 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
|
@override
|
||||||
void initServiceExtensions() {
|
void initServiceExtensions() {
|
||||||
super.initServiceExtensions();
|
super.initServiceExtensions();
|
||||||
|
@ -113,9 +113,9 @@ class Ticker {
|
|||||||
return false;
|
return false;
|
||||||
if (muted)
|
if (muted)
|
||||||
return false;
|
return false;
|
||||||
if (SchedulerBinding.instance!.framesEnabled)
|
if (SchedulerBinding.instance.framesEnabled)
|
||||||
return true;
|
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 true; // for example, we might be in a warm-up frame or forced frame
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -161,9 +161,9 @@ class Ticker {
|
|||||||
if (shouldScheduleTick) {
|
if (shouldScheduleTick) {
|
||||||
scheduleTick();
|
scheduleTick();
|
||||||
}
|
}
|
||||||
if (SchedulerBinding.instance!.schedulerPhase.index > SchedulerPhase.idle.index &&
|
if (SchedulerBinding.instance.schedulerPhase.index > SchedulerPhase.idle.index &&
|
||||||
SchedulerBinding.instance!.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index)
|
SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index)
|
||||||
_startTime = SchedulerBinding.instance!.currentFrameTimeStamp;
|
_startTime = SchedulerBinding.instance.currentFrameTimeStamp;
|
||||||
return _future!;
|
return _future!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ class Ticker {
|
|||||||
void scheduleTick({ bool rescheduling = false }) {
|
void scheduleTick({ bool rescheduling = false }) {
|
||||||
assert(!scheduled);
|
assert(!scheduled);
|
||||||
assert(shouldScheduleTick);
|
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.
|
/// Cancels the frame callback that was requested by [scheduleTick], if any.
|
||||||
@ -262,7 +262,7 @@ class Ticker {
|
|||||||
@protected
|
@protected
|
||||||
void unscheduleTick() {
|
void unscheduleTick() {
|
||||||
if (scheduled) {
|
if (scheduled) {
|
||||||
SchedulerBinding.instance!.cancelFrameCallbackWithId(_animationId!);
|
SchedulerBinding.instance.cancelFrameCallbackWithId(_animationId!);
|
||||||
_animationId = null;
|
_animationId = null;
|
||||||
}
|
}
|
||||||
assert(!shouldScheduleTick);
|
assert(!shouldScheduleTick);
|
||||||
|
@ -13,10 +13,6 @@ export 'dart:ui' show AccessibilityFeatures;
|
|||||||
/// The glue between the semantics layer and the Flutter engine.
|
/// The glue between the semantics layer and the Flutter engine.
|
||||||
// TODO(jonahwilliams): move the remaining semantic related bindings here.
|
// TODO(jonahwilliams): move the remaining semantic related bindings here.
|
||||||
mixin SemanticsBinding on BindingBase {
|
mixin SemanticsBinding on BindingBase {
|
||||||
/// The current [SemanticsBinding], if one has been created.
|
|
||||||
static SemanticsBinding? get instance => _instance;
|
|
||||||
static SemanticsBinding? _instance;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initInstances() {
|
void initInstances() {
|
||||||
super.initInstances();
|
super.initInstances();
|
||||||
@ -24,6 +20,14 @@ mixin SemanticsBinding on BindingBase {
|
|||||||
_accessibilityFeatures = window.accessibilityFeatures;
|
_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.
|
/// Called when the platform accessibility features change.
|
||||||
///
|
///
|
||||||
/// See [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged].
|
/// See [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged].
|
||||||
|
@ -2938,7 +2938,7 @@ class SemanticsOwner extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
|
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) {
|
for (final SemanticsNode node in visitedNodes) {
|
||||||
assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
|
assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
|
||||||
// The _serialize() method marks the node as not dirty, and
|
// The _serialize() method marks the node as not dirty, and
|
||||||
@ -2959,7 +2959,7 @@ class SemanticsOwner extends ChangeNotifier {
|
|||||||
final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
|
final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
|
||||||
builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
|
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();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ class PlatformAssetBundle extends CachingAssetBundle {
|
|||||||
Future<ByteData> load(String key) async {
|
Future<ByteData> load(String key) async {
|
||||||
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path);
|
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path);
|
||||||
final ByteData? asset =
|
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)
|
if (asset == null)
|
||||||
throw FlutterError('Unable to load asset: $key');
|
throw FlutterError('Unable to load asset: $key');
|
||||||
return asset;
|
return asset;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
@ -39,7 +38,11 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The current [ServicesBinding], if one has been created.
|
/// 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;
|
static ServicesBinding? _instance;
|
||||||
|
|
||||||
/// The default instance of [BinaryMessenger].
|
/// The default instance of [BinaryMessenger].
|
||||||
|
@ -45,7 +45,7 @@ class BasicMessageChannel<T> {
|
|||||||
final MessageCodec<T> codec;
|
final MessageCodec<T> codec;
|
||||||
|
|
||||||
/// The messenger which sends the bytes for this channel, not null.
|
/// 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;
|
final BinaryMessenger? _binaryMessenger;
|
||||||
|
|
||||||
/// Sends the specified [message] to the platform plugins on this channel.
|
/// 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 used by this channel to send platform messages.
|
||||||
///
|
///
|
||||||
/// The messenger may not be null.
|
/// The messenger may not be null.
|
||||||
BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger;
|
BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger;
|
||||||
final BinaryMessenger? _binaryMessenger;
|
final BinaryMessenger? _binaryMessenger;
|
||||||
|
|
||||||
/// Backend implementation of [invokeMethod].
|
/// Backend implementation of [invokeMethod].
|
||||||
@ -450,7 +450,7 @@ class EventChannel {
|
|||||||
final MethodCodec codec;
|
final MethodCodec codec;
|
||||||
|
|
||||||
/// The messenger used by this channel to send platform messages, not null.
|
/// 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;
|
final BinaryMessenger? _binaryMessenger;
|
||||||
|
|
||||||
/// Sets up a broadcast stream for receiving events on this channel.
|
/// Sets up a broadcast stream for receiving events on this channel.
|
||||||
|
@ -264,7 +264,7 @@ class RestorationManager extends ChangeNotifier {
|
|||||||
|
|
||||||
_isReplacing = _rootBucketIsValid && enabled;
|
_isReplacing = _rootBucketIsValid && enabled;
|
||||||
if (_isReplacing) {
|
if (_isReplacing) {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_isReplacing = false;
|
_isReplacing = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -350,7 +350,7 @@ class RestorationManager extends ChangeNotifier {
|
|||||||
_bucketsNeedingSerialization.add(bucket);
|
_bucketsNeedingSerialization.add(bucket);
|
||||||
if (!_serializationScheduled) {
|
if (!_serializationScheduled) {
|
||||||
_serializationScheduled = true;
|
_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.
|
/// current restoration data is directly sent to the engine.
|
||||||
void flushData() {
|
void flushData() {
|
||||||
assert(!_debugDoingUpdate);
|
assert(!_debugDoingUpdate);
|
||||||
if (SchedulerBinding.instance!.hasScheduledFrame) {
|
if (SchedulerBinding.instance.hasScheduledFrame) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_doSerialization();
|
_doSerialization();
|
||||||
|
@ -502,7 +502,7 @@ class SystemChrome {
|
|||||||
/// [SystemUiMode.leanBack].
|
/// [SystemUiMode.leanBack].
|
||||||
///
|
///
|
||||||
static Future<void> setSystemUIChangeCallback(SystemUiChangeCallback? callback) async {
|
static Future<void> setSystemUIChangeCallback(SystemUiChangeCallback? callback) async {
|
||||||
ServicesBinding.instance!.setSystemUiChangeCallback(callback);
|
ServicesBinding.instance.setSystemUiChangeCallback(callback);
|
||||||
// Skip setting up the listener if there is no callback.
|
// Skip setting up the listener if there is no callback.
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
await SystemChannels.platform.invokeMethod<void>(
|
await SystemChannels.platform.invokeMethod<void>(
|
||||||
|
@ -1324,7 +1324,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
_updateHighlightMode(FocusManager.instance.highlightMode);
|
_updateHighlightMode(FocusManager.instance.highlightMode);
|
||||||
});
|
});
|
||||||
FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange);
|
FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange);
|
||||||
@ -1413,7 +1413,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
|
|||||||
return _focused && _canShowHighlight && canRequestFocus(target);
|
return _focused && _canShowHighlight && canRequestFocus(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.persistentCallbacks);
|
assert(SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks);
|
||||||
final FocusableActionDetector oldTarget = oldWidget ?? widget;
|
final FocusableActionDetector oldTarget = oldWidget ?? widget;
|
||||||
final bool didShowHoverHighlight = shouldShowHoverHighlight(oldTarget);
|
final bool didShowHoverHighlight = shouldShowHoverHighlight(oldTarget);
|
||||||
final bool didShowFocusHighlight = shouldShowFocusHighlight(oldTarget);
|
final bool didShowFocusHighlight = shouldShowFocusHighlight(oldTarget);
|
||||||
@ -1434,7 +1434,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
|
|||||||
void didUpdateWidget(FocusableActionDetector oldWidget) {
|
void didUpdateWidget(FocusableActionDetector oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.enabled != oldWidget.enabled) {
|
if (widget.enabled != oldWidget.enabled) {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
_mayTriggerCallback(oldWidget: oldWidget);
|
_mayTriggerCallback(oldWidget: oldWidget);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1257,16 +1257,16 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
// If window.defaultRouteName isn't '/', we should assume it was set
|
// If window.defaultRouteName isn't '/', we should assume it was set
|
||||||
// intentionally via `setInitialRoute`, and should override whatever is in
|
// intentionally via `setInitialRoute`, and should override whatever is in
|
||||||
// [widget.initialRoute].
|
// [widget.initialRoute].
|
||||||
String get _initialRouteName => WidgetsBinding.instance!.window.defaultRouteName != Navigator.defaultRouteName
|
String get _initialRouteName => WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
|
||||||
? WidgetsBinding.instance!.window.defaultRouteName
|
? WidgetsBinding.instance.window.defaultRouteName
|
||||||
: widget.initialRoute ?? WidgetsBinding.instance!.window.defaultRouteName;
|
: widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_updateRouting();
|
_updateRouting();
|
||||||
_locale = _resolveLocales(WidgetsBinding.instance!.window.locales, widget.supportedLocales);
|
_locale = _resolveLocales(WidgetsBinding.instance.window.locales, widget.supportedLocales);
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1277,7 +1277,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_defaultRouteInformationProvider?.dispose();
|
_defaultRouteInformationProvider?.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@ -1681,7 +1681,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACCESSIBILITY
|
// ACCESSIBILITY
|
||||||
@ -1725,7 +1725,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
|
MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
|
||||||
if (!kReleaseMode) {
|
if (!kReleaseMode) {
|
||||||
data = data.copyWith(platformBrightness: debugBrightnessOverride);
|
data = data.copyWith(platformBrightness: debugBrightnessOverride);
|
||||||
}
|
}
|
||||||
@ -1737,7 +1737,7 @@ class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with Widg
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -893,7 +893,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
|
|||||||
AutocompletePreviousOptionIntent: _previousOptionAction,
|
AutocompletePreviousOptionIntent: _previousOptionAction,
|
||||||
AutocompleteNextOptionIntent: _nextOptionAction,
|
AutocompleteNextOptionIntent: _nextOptionAction,
|
||||||
};
|
};
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_updateOverlay();
|
_updateOverlay();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -906,7 +906,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
|
|||||||
widget.textEditingController,
|
widget.textEditingController,
|
||||||
);
|
);
|
||||||
_updateFocusNode(oldWidget.focusNode, widget.focusNode);
|
_updateFocusNode(oldWidget.focusNode, widget.focusNode);
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_updateOverlay();
|
_updateOverlay();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
|
|||||||
// If the child doesn't exist yet, we got called during the very first
|
// 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
|
// build of this subtree. Wait until the end of the frame to update
|
||||||
// the child when the child is guaranteed to be present.
|
// the child when the child is guaranteed to be present.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
|
|||||||
}());
|
}());
|
||||||
_handles!.remove(handle);
|
_handles!.remove(handle);
|
||||||
if (_handles!.isEmpty) {
|
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
|
// Build/layout haven't started yet so let's just schedule this for
|
||||||
// the next frame.
|
// the next frame.
|
||||||
setState(() { _keepingAlive = false; });
|
setState(() { _keepingAlive = false; });
|
||||||
|
@ -69,7 +69,7 @@ class BannerPainter extends CustomPainter {
|
|||||||
assert(location != null),
|
assert(location != null),
|
||||||
assert(color != null),
|
assert(color != null),
|
||||||
assert(textStyle != null),
|
assert(textStyle != null),
|
||||||
super(repaint: PaintingBinding.instance!.systemFonts);
|
super(repaint: PaintingBinding.instance.systemFonts);
|
||||||
|
|
||||||
/// The message to show in the banner.
|
/// The message to show in the banner.
|
||||||
final String message;
|
final String message;
|
||||||
|
@ -50,12 +50,12 @@ export 'dart:ui' show AppLifecycleState, Locale;
|
|||||||
/// @override
|
/// @override
|
||||||
/// void initState() {
|
/// void initState() {
|
||||||
/// super.initState();
|
/// super.initState();
|
||||||
/// WidgetsBinding.instance!.addObserver(this);
|
/// WidgetsBinding.instance.addObserver(this);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
/// void dispose() {
|
/// void dispose() {
|
||||||
/// WidgetsBinding.instance!.removeObserver(this);
|
/// WidgetsBinding.instance.removeObserver(this);
|
||||||
/// super.dispose();
|
/// super.dispose();
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -147,19 +147,19 @@ abstract class WidgetsBindingObserver {
|
|||||||
/// @override
|
/// @override
|
||||||
/// void initState() {
|
/// void initState() {
|
||||||
/// super.initState();
|
/// super.initState();
|
||||||
/// _lastSize = WidgetsBinding.instance!.window.physicalSize;
|
/// _lastSize = WidgetsBinding.instance.window.physicalSize;
|
||||||
/// WidgetsBinding.instance!.addObserver(this);
|
/// WidgetsBinding.instance.addObserver(this);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
/// void dispose() {
|
/// void dispose() {
|
||||||
/// WidgetsBinding.instance!.removeObserver(this);
|
/// WidgetsBinding.instance.removeObserver(this);
|
||||||
/// super.dispose();
|
/// super.dispose();
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
/// void didChangeMetrics() {
|
/// void didChangeMetrics() {
|
||||||
/// setState(() { _lastSize = WidgetsBinding.instance!.window.physicalSize; });
|
/// setState(() { _lastSize = WidgetsBinding.instance.window.physicalSize; });
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
@ -203,12 +203,12 @@ abstract class WidgetsBindingObserver {
|
|||||||
/// @override
|
/// @override
|
||||||
/// void initState() {
|
/// void initState() {
|
||||||
/// super.initState();
|
/// super.initState();
|
||||||
/// WidgetsBinding.instance!.addObserver(this);
|
/// WidgetsBinding.instance.addObserver(this);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
/// void dispose() {
|
/// void dispose() {
|
||||||
/// WidgetsBinding.instance!.removeObserver(this);
|
/// WidgetsBinding.instance.removeObserver(this);
|
||||||
/// super.dispose();
|
/// super.dispose();
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -216,7 +216,7 @@ abstract class WidgetsBindingObserver {
|
|||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
/// void didChangeTextScaleFactor() {
|
/// void didChangeTextScaleFactor() {
|
||||||
/// setState(() { _lastTextScaleFactor = WidgetsBinding.instance!.window.textScaleFactor; });
|
/// setState(() { _lastTextScaleFactor = WidgetsBinding.instance.window.textScaleFactor; });
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @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() {
|
void _debugAddStackFilters() {
|
||||||
const PartialStackFrame elementInflateWidget = PartialStackFrame(package: 'package:flutter/src/widgets/framework.dart', className: 'Element', method: 'inflateWidget');
|
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');
|
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
|
@override
|
||||||
void initServiceExtensions() {
|
void initServiceExtensions() {
|
||||||
super.initServiceExtensions();
|
super.initServiceExtensions();
|
||||||
@ -862,14 +862,14 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
|
|||||||
developer.Timeline.instantSync('Rasterized first useful frame');
|
developer.Timeline.instantSync('Rasterized first useful frame');
|
||||||
developer.postEvent('Flutter.FirstFrame', <String, dynamic>{});
|
developer.postEvent('Flutter.FirstFrame', <String, dynamic>{});
|
||||||
}
|
}
|
||||||
SchedulerBinding.instance!.removeTimingsCallback(firstFrameCallback!);
|
SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!);
|
||||||
firstFrameCallback = null;
|
firstFrameCallback = null;
|
||||||
_firstFrameCompleter.complete();
|
_firstFrameCompleter.complete();
|
||||||
};
|
};
|
||||||
// Callback is only invoked when FlutterView.render is called. When
|
// Callback is only invoked when FlutterView.render is called. When
|
||||||
// sendFramesToEngine is set to false during the frame, it will not be
|
// sendFramesToEngine is set to false during the frame, it will not be
|
||||||
// called and we need to remove the callback (see below).
|
// called and we need to remove the callback (see below).
|
||||||
SchedulerBinding.instance!.addTimingsCallback(firstFrameCallback!);
|
SchedulerBinding.instance.addTimingsCallback(firstFrameCallback!);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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
|
// This frame is deferred and not the first frame sent to the engine that
|
||||||
// should be reported.
|
// should be reported.
|
||||||
_needToReportFirstFrame = true;
|
_needToReportFirstFrame = true;
|
||||||
SchedulerBinding.instance!.removeTimingsCallback(firstFrameCallback!);
|
SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,7 +938,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
|
|||||||
child: rootWidget,
|
child: rootWidget,
|
||||||
).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?);
|
).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?);
|
||||||
if (isBootstrapFrame) {
|
if (isBootstrapFrame) {
|
||||||
SchedulerBinding.instance!.ensureVisualUpdate();
|
SchedulerBinding.instance.ensureVisualUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,12 +1033,11 @@ void runApp(Widget app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _debugDumpAppString() {
|
String _debugDumpAppString() {
|
||||||
assert(WidgetsBinding.instance != null);
|
const String mode = kDebugMode ? 'DEBUG MODE' : kReleaseMode ? 'RELEASE MODE' : 'PROFILE MODE';
|
||||||
const String mode = kDebugMode ? 'DEBUG MODE' : 'PROFILE MODE';
|
|
||||||
final StringBuffer buffer = StringBuffer();
|
final StringBuffer buffer = StringBuffer();
|
||||||
buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode');
|
buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode');
|
||||||
if (WidgetsBinding.instance!.renderViewElement != null) {
|
if (WidgetsBinding.instance.renderViewElement != null) {
|
||||||
buffer.writeln(WidgetsBinding.instance!.renderViewElement!.toStringDeep());
|
buffer.writeln(WidgetsBinding.instance.renderViewElement!.toStringDeep());
|
||||||
} else {
|
} else {
|
||||||
buffer.writeln('<no tree currently mounted>');
|
buffer.writeln('<no tree currently mounted>');
|
||||||
}
|
}
|
||||||
@ -1047,8 +1046,7 @@ String _debugDumpAppString() {
|
|||||||
|
|
||||||
/// Print a string representation of the currently running app.
|
/// Print a string representation of the currently running app.
|
||||||
void debugDumpApp() {
|
void debugDumpApp() {
|
||||||
final String value = _debugDumpAppString();
|
debugPrint(_debugDumpAppString());
|
||||||
debugPrint(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A bridge from a [RenderObject] to an [Element] tree.
|
/// A bridge from a [RenderObject] to an [Element] tree.
|
||||||
@ -1229,22 +1227,34 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
|
|||||||
/// A concrete binding for applications based on the Widgets framework.
|
/// A concrete binding for applications based on the Widgets framework.
|
||||||
///
|
///
|
||||||
/// This is the glue that binds the framework to the Flutter engine.
|
/// 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 {
|
class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
|
||||||
|
/// Returns an instance of the binding that implements
|
||||||
/// Returns an instance of the [WidgetsBinding], creating and
|
/// [WidgetsBinding]. If no binding has yet been initialized, the
|
||||||
/// initializing it if necessary. If one is created, it will be a
|
/// [WidgetsFlutterBinding] class is used to create and initialize
|
||||||
/// [WidgetsFlutterBinding]. If one was previously initialized, then
|
/// one.
|
||||||
/// it will at least implement [WidgetsBinding].
|
|
||||||
///
|
///
|
||||||
/// You only need to call this method if you need the binding to be
|
/// You only need to call this method if you need the binding to be
|
||||||
/// initialized before calling [runApp].
|
/// initialized before calling [runApp].
|
||||||
///
|
///
|
||||||
/// In the `flutter_test` framework, [testWidgets] initializes the
|
/// In the `flutter_test` framework, [testWidgets] initializes the
|
||||||
/// binding instance to a [TestWidgetsFlutterBinding], not a
|
/// binding instance to a [TestWidgetsFlutterBinding], not a
|
||||||
/// [WidgetsFlutterBinding].
|
/// [WidgetsFlutterBinding]. See
|
||||||
|
/// [TestWidgetsFlutterBinding.ensureInitialized].
|
||||||
static WidgetsBinding ensureInitialized() {
|
static WidgetsBinding ensureInitialized() {
|
||||||
if (WidgetsBinding.instance == null)
|
if (WidgetsBinding._instance == null)
|
||||||
WidgetsFlutterBinding();
|
WidgetsFlutterBinding();
|
||||||
return WidgetsBinding.instance!;
|
return WidgetsBinding.instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,7 +919,7 @@ class _DragAvatar<T extends Object> extends Drag {
|
|||||||
_lastOffset = globalPosition - dragStartPoint;
|
_lastOffset = globalPosition - dragStartPoint;
|
||||||
_entry!.markNeedsBuild();
|
_entry!.markNeedsBuild();
|
||||||
final HitTestResult result = HitTestResult();
|
final HitTestResult result = HitTestResult();
|
||||||
WidgetsBinding.instance!.hitTest(result, globalPosition + feedbackOffset);
|
WidgetsBinding.instance.hitTest(result, globalPosition + feedbackOffset);
|
||||||
|
|
||||||
final List<_DragTargetState<Object>> targets = _getDragTargets(result.path).toList();
|
final List<_DragTargetState<Object>> targets = _getDragTargets(result.path).toList();
|
||||||
|
|
||||||
|
@ -1625,7 +1625,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
|
|
||||||
if (!_didAutoFocus && widget.autofocus) {
|
if (!_didAutoFocus && widget.autofocus) {
|
||||||
_didAutoFocus = true;
|
_didAutoFocus = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
FocusScope.of(context).autofocus(widget.focusNode);
|
FocusScope.of(context).autofocus(widget.focusNode);
|
||||||
}
|
}
|
||||||
@ -1700,7 +1700,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
_selectionOverlay = null;
|
_selectionOverlay = null;
|
||||||
_focusAttachment!.detach();
|
_focusAttachment!.detach();
|
||||||
widget.focusNode.removeListener(_handleFocusChanged);
|
widget.focusNode.removeListener(_handleFocusChanged);
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
_clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
||||||
_clipboardStatus?.dispose();
|
_clipboardStatus?.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@ -2219,7 +2219,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_showCaretOnScreenScheduled = true;
|
_showCaretOnScreenScheduled = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
|
||||||
_showCaretOnScreenScheduled = false;
|
_showCaretOnScreenScheduled = false;
|
||||||
if (_currentCaretRect == null || !_scrollController!.hasClients) {
|
if (_currentCaretRect == null || !_scrollController!.hasClients) {
|
||||||
return;
|
return;
|
||||||
@ -2272,10 +2272,10 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeMetrics() {
|
void didChangeMetrics() {
|
||||||
if (_lastBottomViewInset < WidgetsBinding.instance!.window.viewInsets.bottom) {
|
if (_lastBottomViewInset < WidgetsBinding.instance.window.viewInsets.bottom) {
|
||||||
_scheduleShowCaretOnScreen();
|
_scheduleShowCaretOnScreen();
|
||||||
}
|
}
|
||||||
_lastBottomViewInset = WidgetsBinding.instance!.window.viewInsets.bottom;
|
_lastBottomViewInset = WidgetsBinding.instance.window.viewInsets.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@pragma('vm:notify-debugger-on-exception')
|
@pragma('vm:notify-debugger-on-exception')
|
||||||
@ -2432,8 +2432,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
_updateOrDisposeSelectionOverlayIfNeeded();
|
_updateOrDisposeSelectionOverlayIfNeeded();
|
||||||
if (_hasFocus) {
|
if (_hasFocus) {
|
||||||
// Listen for changing viewInsets, which indicates keyboard showing up.
|
// Listen for changing viewInsets, which indicates keyboard showing up.
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
_lastBottomViewInset = WidgetsBinding.instance!.window.viewInsets.bottom;
|
_lastBottomViewInset = WidgetsBinding.instance.window.viewInsets.bottom;
|
||||||
if (!widget.readOnly) {
|
if (!widget.readOnly) {
|
||||||
_scheduleShowCaretOnScreen();
|
_scheduleShowCaretOnScreen();
|
||||||
}
|
}
|
||||||
@ -2442,7 +2442,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
_handleSelectionChanged(TextSelection.collapsed(offset: _value.text.length), null);
|
_handleSelectionChanged(TextSelection.collapsed(offset: _value.text.length), null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
// Clear the selection and composition state if this widget lost focus.
|
// Clear the selection and composition state if this widget lost focus.
|
||||||
_value = TextEditingValue(text: _value.text);
|
_value = TextEditingValue(text: _value.text);
|
||||||
_currentPromptRectRange = null;
|
_currentPromptRectRange = null;
|
||||||
@ -2455,8 +2455,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
final Size size = renderEditable.size;
|
final Size size = renderEditable.size;
|
||||||
final Matrix4 transform = renderEditable.getTransformTo(null);
|
final Matrix4 transform = renderEditable.getTransformTo(null);
|
||||||
_textInputConnection!.setEditableSizeAndTransform(size, transform);
|
_textInputConnection!.setEditableSizeAndTransform(size, transform);
|
||||||
SchedulerBinding.instance!
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateSizeAndTransform());
|
||||||
.addPostFrameCallback((Duration _) => _updateSizeAndTransform());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2478,8 +2477,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
}
|
}
|
||||||
assert(composingRect != null);
|
assert(composingRect != null);
|
||||||
_textInputConnection!.setComposingRect(composingRect);
|
_textInputConnection!.setComposingRect(composingRect);
|
||||||
SchedulerBinding.instance!
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateComposingRectIfNeeded());
|
||||||
.addPostFrameCallback((Duration _) => _updateComposingRectIfNeeded());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2491,8 +2489,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
final Rect caretRect = renderEditable.getLocalRectForCaret(currentTextPosition);
|
final Rect caretRect = renderEditable.getLocalRectForCaret(currentTextPosition);
|
||||||
_textInputConnection!.setCaretRect(caretRect);
|
_textInputConnection!.setCaretRect(caretRect);
|
||||||
}
|
}
|
||||||
SchedulerBinding.instance!
|
SchedulerBinding.instance.addPostFrameCallback((Duration _) => _updateCaretRectIfNeeded());
|
||||||
.addPostFrameCallback((Duration _) => _updateCaretRectIfNeeded());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1465,21 +1465,21 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier {
|
|||||||
void registerGlobalHandlers() {
|
void registerGlobalHandlers() {
|
||||||
assert(RawKeyboard.instance.keyEventHandler == null);
|
assert(RawKeyboard.instance.keyEventHandler == null);
|
||||||
RawKeyboard.instance.keyEventHandler = _handleRawKeyEvent;
|
RawKeyboard.instance.keyEventHandler = _handleRawKeyEvent;
|
||||||
GestureBinding.instance!.pointerRouter.addGlobalRoute(_handlePointerEvent);
|
GestureBinding.instance.pointerRouter.addGlobalRoute(_handlePointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
if (RawKeyboard.instance.keyEventHandler == _handleRawKeyEvent) {
|
if (RawKeyboard.instance.keyEventHandler == _handleRawKeyEvent) {
|
||||||
RawKeyboard.instance.keyEventHandler = null;
|
RawKeyboard.instance.keyEventHandler = null;
|
||||||
GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handlePointerEvent);
|
GestureBinding.instance.pointerRouter.removeGlobalRoute(_handlePointerEvent);
|
||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides convenient access to the current [FocusManager] singleton from
|
/// Provides convenient access to the current [FocusManager] singleton from
|
||||||
/// the [WidgetsBinding] instance.
|
/// 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.
|
/// Sets the strategy by which [highlightMode] is determined.
|
||||||
///
|
///
|
||||||
@ -1522,7 +1522,7 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier {
|
|||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
case TargetPlatform.fuchsia:
|
case TargetPlatform.fuchsia:
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
if (WidgetsBinding.instance!.mouseTracker.mouseIsConnected) {
|
if (WidgetsBinding.instance.mouseTracker.mouseIsConnected) {
|
||||||
return FocusHighlightMode.traditional;
|
return FocusHighlightMode.traditional;
|
||||||
}
|
}
|
||||||
return FocusHighlightMode.touch;
|
return FocusHighlightMode.touch;
|
||||||
@ -1821,7 +1821,7 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier {
|
|||||||
|
|
||||||
/// Provides convenient access to the current [FocusManager.primaryFocus] from the
|
/// Provides convenient access to the current [FocusManager.primaryFocus] from the
|
||||||
/// [WidgetsBinding] instance.
|
/// [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
|
/// Returns a text representation of the current focus tree, along with the
|
||||||
/// current attributes on each node.
|
/// current attributes on each node.
|
||||||
|
@ -149,7 +149,7 @@ abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
|
|||||||
/// constructor.
|
/// constructor.
|
||||||
const GlobalKey.constructor() : super.empty();
|
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.
|
/// The build context in which the widget with this key builds.
|
||||||
///
|
///
|
||||||
|
@ -930,7 +930,7 @@ class HeroController extends NavigatorObserver {
|
|||||||
// going to end up, and the `to` route will go back onstage.
|
// going to end up, and the `to` route will go back onstage.
|
||||||
to.offstage = to.animation!.value == 0.0;
|
to.offstage = to.animation!.value == 0.0;
|
||||||
|
|
||||||
WidgetsBinding.instance!.addPostFrameCallback((Duration value) {
|
WidgetsBinding.instance.addPostFrameCallback((Duration value) {
|
||||||
_startHeroTransition(from, to, animation, flightType, isUserGestureTransition);
|
_startHeroTransition(from, to, animation, flightType, isUserGestureTransition);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ Future<void> precacheImage(
|
|||||||
// Give callers until at least the end of the frame to subscribe to the
|
// Give callers until at least the end of the frame to subscribe to the
|
||||||
// image stream.
|
// image stream.
|
||||||
// See ImageCache._liveImages
|
// See ImageCache._liveImages
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
stream.removeListener(listener!);
|
stream.removeListener(listener!);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -1118,14 +1118,14 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
_scrollAwareContext = DisposableBuildContext<State<Image>>(this);
|
_scrollAwareContext = DisposableBuildContext<State<Image>>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
assert(_imageStream != null);
|
assert(_imageStream != null);
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_stopListeningToStream();
|
_stopListeningToStream();
|
||||||
_completerHandle?.dispose();
|
_completerHandle?.dispose();
|
||||||
_scrollAwareContext.dispose();
|
_scrollAwareContext.dispose();
|
||||||
@ -1175,7 +1175,7 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
void _updateInvertColors() {
|
void _updateInvertColors() {
|
||||||
_invertColors = MediaQuery.maybeOf(context)?.invertColors
|
_invertColors = MediaQuery.maybeOf(context)?.invertColors
|
||||||
?? SemanticsBinding.instance!.accessibilityFeatures.invertColors;
|
?? SemanticsBinding.instance.accessibilityFeatures.invertColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _resolveImage() {
|
void _resolveImage() {
|
||||||
|
@ -759,7 +759,7 @@ class _ListWheelScrollViewState extends State<ListWheelScrollView> {
|
|||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.controller != null && widget.controller != scrollController) {
|
if (widget.controller != null && widget.controller != scrollController) {
|
||||||
final ScrollController? oldScrollController = scrollController;
|
final ScrollController? oldScrollController = scrollController;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
oldScrollController!.dispose();
|
oldScrollController!.dispose();
|
||||||
});
|
});
|
||||||
scrollController = widget.controller;
|
scrollController = widget.controller;
|
||||||
|
@ -543,7 +543,7 @@ class _LocalizationsState extends State<Localizations> {
|
|||||||
// have finished loading. Until then the old locale will continue to be used.
|
// 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
|
// - If we're running at app startup time then defer reporting the first
|
||||||
// "useful" frame until after the async load has completed.
|
// "useful" frame until after the async load has completed.
|
||||||
RendererBinding.instance!.deferFirstFrame();
|
RendererBinding.instance.deferFirstFrame();
|
||||||
typeToResourcesFuture.then<void>((Map<Type, dynamic> value) {
|
typeToResourcesFuture.then<void>((Map<Type, dynamic> value) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -551,7 +551,7 @@ class _LocalizationsState extends State<Localizations> {
|
|||||||
_locale = locale;
|
_locale = locale;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RendererBinding.instance!.allowFirstFrame();
|
RendererBinding.instance.allowFirstFrame();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3513,7 +3513,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
|||||||
// controller at the end of the build.
|
// controller at the end of the build.
|
||||||
if (newHeroController.navigator != null) {
|
if (newHeroController.navigator != null) {
|
||||||
final NavigatorState previousOwner = newHeroController.navigator!;
|
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.
|
// We only check if this navigator still owns the hero controller.
|
||||||
if (_heroControllerFromScope == newHeroController) {
|
if (_heroControllerFromScope == newHeroController) {
|
||||||
final bool hasHeroControllerOwnerShip = _heroControllerFromScope!._navigator == this;
|
final bool hasHeroControllerOwnerShip = _heroControllerFromScope!._navigator == this;
|
||||||
@ -5319,7 +5319,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
|||||||
|
|
||||||
void _cancelActivePointers() {
|
void _cancelActivePointers() {
|
||||||
// TODO(abarth): This mechanism is far from perfect. See https://github.com/flutter/flutter/issues/4770
|
// 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
|
// If we're between frames (SchedulerPhase.idle) then absorb any
|
||||||
// subsequent pointers from this frame. The absorbing flag will be
|
// subsequent pointers from this frame. The absorbing flag will be
|
||||||
// reset in the next frame, see build().
|
// reset in the next frame, see build().
|
||||||
@ -5330,7 +5330,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
|||||||
// to false on the next frame.
|
// to false on the next frame.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_activePointers.toList().forEach(WidgetsBinding.instance!.cancelPointer);
|
_activePointers.toList().forEach(WidgetsBinding.instance.cancelPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1332,7 +1332,7 @@ class _NestedScrollController extends ScrollController {
|
|||||||
// the position change notifications because those happen synchronously
|
// the position change notifications because those happen synchronously
|
||||||
// during a frame, at a time where it's too late to call setState. Since the
|
// 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.
|
// result is usually animated, the lag incurred is no big deal.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback(
|
SchedulerBinding.instance.addPostFrameCallback(
|
||||||
(Duration timeStamp) {
|
(Duration timeStamp) {
|
||||||
coordinator.updateShadow();
|
coordinator.updateShadow();
|
||||||
},
|
},
|
||||||
|
@ -151,8 +151,8 @@ class OverlayEntry extends ChangeNotifier {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
overlay._entries.remove(this);
|
overlay._entries.remove(this);
|
||||||
if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) {
|
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
overlay._markDirty();
|
overlay._markDirty();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -627,7 +627,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
|
|||||||
item.dragging = true;
|
item.dragging = true;
|
||||||
item.rebuild();
|
item.rebuild();
|
||||||
_dragStartTransitionComplete = false;
|
_dragStartTransitionComplete = false;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
_dragStartTransitionComplete = true;
|
_dragStartTransitionComplete = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -275,18 +275,18 @@ class _RootRestorationScopeState extends State<RootRestorationScope> {
|
|||||||
void _loadRootBucketIfNecessary() {
|
void _loadRootBucketIfNecessary() {
|
||||||
if (_isWaitingForRootBucket && !_isLoadingRootBucket) {
|
if (_isWaitingForRootBucket && !_isLoadingRootBucket) {
|
||||||
_isLoadingRootBucket = true;
|
_isLoadingRootBucket = true;
|
||||||
RendererBinding.instance!.deferFirstFrame();
|
RendererBinding.instance.deferFirstFrame();
|
||||||
ServicesBinding.instance!.restorationManager.rootBucket.then((RestorationBucket? bucket) {
|
ServicesBinding.instance.restorationManager.rootBucket.then((RestorationBucket? bucket) {
|
||||||
_isLoadingRootBucket = false;
|
_isLoadingRootBucket = false;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ServicesBinding.instance!.restorationManager.addListener(_replaceRootBucket);
|
ServicesBinding.instance.restorationManager.addListener(_replaceRootBucket);
|
||||||
setState(() {
|
setState(() {
|
||||||
_rootBucket = bucket;
|
_rootBucket = bucket;
|
||||||
_rootBucketValid = true;
|
_rootBucketValid = true;
|
||||||
_okToRenderBlankContainer = false;
|
_okToRenderBlankContainer = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RendererBinding.instance!.allowFirstFrame();
|
RendererBinding.instance.allowFirstFrame();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ class _RootRestorationScopeState extends State<RootRestorationScope> {
|
|||||||
void _replaceRootBucket() {
|
void _replaceRootBucket() {
|
||||||
_rootBucketValid = false;
|
_rootBucketValid = false;
|
||||||
_rootBucket = null;
|
_rootBucket = null;
|
||||||
ServicesBinding.instance!.restorationManager.removeListener(_replaceRootBucket);
|
ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket);
|
||||||
_loadRootBucketIfNecessary();
|
_loadRootBucketIfNecessary();
|
||||||
assert(!_isWaitingForRootBucket); // Ensure that load finished synchronously.
|
assert(!_isWaitingForRootBucket); // Ensure that load finished synchronously.
|
||||||
}
|
}
|
||||||
@ -302,7 +302,7 @@ class _RootRestorationScopeState extends State<RootRestorationScope> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
if (_rootBucketValid) {
|
if (_rootBucketValid) {
|
||||||
ServicesBinding.instance!.restorationManager.removeListener(_replaceRootBucket);
|
ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket);
|
||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
@ -504,7 +504,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
|
|||||||
return;
|
return;
|
||||||
assert(_currentIntentionToReport != _IntentionToReportRouteInformation.none);
|
assert(_currentIntentionToReport != _IntentionToReportRouteInformation.none);
|
||||||
_routeInformationReportingTaskScheduled = true;
|
_routeInformationReportingTaskScheduled = true;
|
||||||
SchedulerBinding.instance!.addPostFrameCallback(_reportRouteInformation);
|
SchedulerBinding.instance.addPostFrameCallback(_reportRouteInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reportRouteInformation(Duration timestamp) {
|
void _reportRouteInformation(Duration timestamp) {
|
||||||
@ -962,7 +962,7 @@ class RootBackButtonDispatcher extends BackButtonDispatcher with WidgetsBindingO
|
|||||||
@override
|
@override
|
||||||
void addCallback(ValueGetter<Future<bool>> callback) {
|
void addCallback(ValueGetter<Future<bool>> callback) {
|
||||||
if (!hasCallbacks)
|
if (!hasCallbacks)
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
super.addCallback(callback);
|
super.addCallback(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,7 +970,7 @@ class RootBackButtonDispatcher extends BackButtonDispatcher with WidgetsBindingO
|
|||||||
void removeCallback(ValueGetter<Future<bool>> callback) {
|
void removeCallback(ValueGetter<Future<bool>> callback) {
|
||||||
super.removeCallback(callback);
|
super.removeCallback(callback);
|
||||||
if (!hasCallbacks)
|
if (!hasCallbacks)
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1356,7 +1356,7 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid
|
|||||||
@override
|
@override
|
||||||
void addListener(VoidCallback listener) {
|
void addListener(VoidCallback listener) {
|
||||||
if (!hasListeners)
|
if (!hasListeners)
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1364,7 +1364,7 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid
|
|||||||
void removeListener(VoidCallback listener) {
|
void removeListener(VoidCallback listener) {
|
||||||
super.removeListener(listener);
|
super.removeListener(listener);
|
||||||
if (!hasListeners)
|
if (!hasListeners)
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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
|
// is no longer being used, there's no listener, and so it will get garbage
|
||||||
// collected.
|
// collected.
|
||||||
if (hasListeners)
|
if (hasListeners)
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,11 +616,11 @@ mixin LocalHistoryRoute<T> on Route<T> {
|
|||||||
entry._owner = null;
|
entry._owner = null;
|
||||||
entry._notifyRemoved();
|
entry._notifyRemoved();
|
||||||
if (_localHistory!.isEmpty) {
|
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
|
// The local history might be removed as a result of disposing inactive
|
||||||
// elements during finalizeTree. The state is locked at this moment, and
|
// elements during finalizeTree. The state is locked at this moment, and
|
||||||
// we can only notify state has changed in the next frame.
|
// we can only notify state has changed in the next frame.
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||||
changedInternalState();
|
changedInternalState();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +83,7 @@ class ScrollAwareImageProvider<T extends Object> extends ImageProvider<T> {
|
|||||||
// Do this before checking scrolling, so that if the bytes are available we
|
// 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
|
// render them even though we're scrolling fast - there's no additional
|
||||||
// allocations to do for texture memory, it's already there.
|
// 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);
|
imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ class ScrollAwareImageProvider<T extends Object> extends ImageProvider<T> {
|
|||||||
// Try to get to end of the frame callbacks of the next frame, and then
|
// Try to get to end of the frame callbacks of the next frame, and then
|
||||||
// check again.
|
// check again.
|
||||||
if (Scrollable.recommendDeferredLoadingForContext(context.context!)) {
|
if (Scrollable.recommendDeferredLoadingForContext(context.context!)) {
|
||||||
SchedulerBinding.instance!.scheduleFrameCallback((_) {
|
SchedulerBinding.instance.scheduleFrameCallback((Duration timeStamp) {
|
||||||
scheduleMicrotask(() => resolveStreamForKey(configuration, stream, key, handleError));
|
scheduleMicrotask(() => resolveStreamForKey(configuration, stream, key, handleError));
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -224,7 +224,7 @@ class ScrollPhysics {
|
|||||||
assert(metrics != null);
|
assert(metrics != null);
|
||||||
assert(context != null);
|
assert(context != null);
|
||||||
if (parent == 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 velocity.abs() > maxPhysicalPixels;
|
||||||
}
|
}
|
||||||
return parent!.recommendDeferredLoading(velocity, metrics, context);
|
return parent!.recommendDeferredLoading(velocity, metrics, context);
|
||||||
@ -356,8 +356,8 @@ class ScrollPhysics {
|
|||||||
static final Tolerance _kDefaultTolerance = Tolerance(
|
static final Tolerance _kDefaultTolerance = Tolerance(
|
||||||
// TODO(ianh): Handle the case of the device pixel ratio changing.
|
// 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.
|
// 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
|
velocity: 1.0 / (0.050 * WidgetsBinding.instance.window.devicePixelRatio), // logical pixels per second
|
||||||
distance: 1.0 / WidgetsBinding.instance!.window.devicePixelRatio, // logical pixels
|
distance: 1.0 / WidgetsBinding.instance.window.devicePixelRatio, // logical pixels
|
||||||
);
|
);
|
||||||
|
|
||||||
/// The tolerance to use for ballistic simulations.
|
/// The tolerance to use for ballistic simulations.
|
||||||
|
@ -254,7 +254,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
|||||||
/// If there is any overscroll, it is reported using [didOverscrollBy].
|
/// If there is any overscroll, it is reported using [didOverscrollBy].
|
||||||
double setPixels(double newPixels) {
|
double setPixels(double newPixels) {
|
||||||
assert(hasPixels);
|
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) {
|
if (newPixels != pixels) {
|
||||||
final double overscroll = applyBoundaryConditions(newPixels);
|
final double overscroll = applyBoundaryConditions(newPixels);
|
||||||
assert(() {
|
assert(() {
|
||||||
@ -375,7 +375,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
|||||||
_impliedVelocity = value - pixels;
|
_impliedVelocity = value - pixels;
|
||||||
_pixels = value;
|
_pixels = value;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
|
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
|
||||||
_impliedVelocity = 0;
|
_impliedVelocity = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
|
|||||||
_persistedScrollOffset.value = offset;
|
_persistedScrollOffset.value = offset;
|
||||||
// [saveOffset] is called after a scrolling ends and it is usually not
|
// [saveOffset] is called after a scrolling ends and it is usually not
|
||||||
// followed by a frame. Therefore, manually flush restoration data.
|
// followed by a frame. Therefore, manually flush restoration data.
|
||||||
ServicesBinding.instance!.restorationManager.flushData();
|
ServicesBinding.instance.restorationManager.flushData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -705,7 +705,7 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
|
|||||||
final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
|
final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
|
||||||
// Only express interest in the event if it would actually result in a scroll.
|
// Only express interest in the event if it would actually result in a scroll.
|
||||||
if (delta != 0.0 && targetScrollOffset != position.pixels) {
|
if (delta != 0.0 && targetScrollOffset != position.pixels) {
|
||||||
GestureBinding.instance!.pointerSignalResolver.register(event, _handlePointerScroll);
|
GestureBinding.instance.pointerSignalResolver.register(event, _handlePointerScroll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user