Unverified Commit cb9a3f69 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Add timeline events for post frame callbacks (#136435)

Before this change, long-running post-frame callbacks wouldn't show up in the timeline at all.  This adds a timeline event for post-frame callbacks, with a debug flag that will add timeline events for each individual callback.

#testexempt -- we have no way to test calls to the timeline.
parent 024e0da4
...@@ -585,7 +585,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker ...@@ -585,7 +585,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
_lastOverlayEntry?.dispose(); _lastOverlayEntry?.dispose();
_lastOverlayEntry = null; _lastOverlayEntry = null;
_openController.reset(); _openController.reset();
}); }, debugLabel: 'removeContextMenuDecoy');
case AnimationStatus.forward: case AnimationStatus.forward:
case AnimationStatus.reverse: case AnimationStatus.reverse:
...@@ -1009,7 +1009,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> { ...@@ -1009,7 +1009,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
_updateTweenRects(); _updateTweenRects();
_internalOffstage = false; _internalOffstage = false;
_setOffstageInternally(); _setOffstageInternally();
}); }, debugLabel: 'renderContextMenuRouteOffstage');
return super.didPush(); return super.didPush();
} }
......
...@@ -1007,7 +1007,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> { ...@@ -1007,7 +1007,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
final int position = minCheck ? positionDouble.ceil() : positionDouble.floor(); final int position = minCheck ? positionDouble.ceil() : positionDouble.floor();
_animateColumnControllerToItem(minuteController, position); _animateColumnControllerToItem(minuteController, position);
} }
}); }, debugLabel: 'DatePicker.scrollToDate');
} }
@override @override
...@@ -1401,7 +1401,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> { ...@@ -1401,7 +1401,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
if (selectedDay != newDate.day) { if (selectedDay != newDate.day) {
_animateColumnControllerToItem(dayController, newDate.day - 1); _animateColumnControllerToItem(dayController, newDate.day - 1);
} }
}); }, debugLabel: 'DatePicker.scrollToDate');
} }
@override @override
...@@ -1725,7 +1725,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> { ...@@ -1725,7 +1725,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
if (selectedMonth != newDate.month) { if (selectedMonth != newDate.month) {
_animateColumnControllerToItem(monthController, newDate.month - 1); _animateColumnControllerToItem(monthController, newDate.month - 1);
} }
}); }, debugLabel: 'DatePicker.scrollToDate');
} }
@override @override
......
...@@ -461,7 +461,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo ...@@ -461,7 +461,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
} else { } else {
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
setState(() => hasSliverLayoutExtent = false); setState(() => hasSliverLayoutExtent = false);
}); }, debugLabel: 'Refresh.goToDone');
} }
} }
...@@ -497,7 +497,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo ...@@ -497,7 +497,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
} }
}); });
setState(() => hasSliverLayoutExtent = true); setState(() => hasSliverLayoutExtent = true);
}); }, debugLabel: 'Refresh.transition');
} }
return RefreshIndicatorMode.armed; return RefreshIndicatorMode.armed;
} }
......
...@@ -130,7 +130,7 @@ class CupertinoSpellCheckSuggestionsToolbar extends StatelessWidget { ...@@ -130,7 +130,7 @@ class CupertinoSpellCheckSuggestionsToolbar extends StatelessWidget {
if (editableTextState.mounted) { if (editableTextState.mounted) {
editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent); editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent);
} }
}); }, debugLabel: 'SpellCheckSuggestions.bringIntoView');
editableTextState.hideToolbar(); editableTextState.hideToolbar();
} }
......
...@@ -175,7 +175,7 @@ class _Resampler { ...@@ -175,7 +175,7 @@ class _Resampler {
_timer = Timer.periodic(_samplingInterval, (_) => _onSampleTimeChanged()); _timer = Timer.periodic(_samplingInterval, (_) => _onSampleTimeChanged());
// Trigger an immediate sample time change. // Trigger an immediate sample time change.
_onSampleTimeChanged(); _onSampleTimeChanged();
}); }, debugLabel: 'Resampler.startTimer');
} }
} }
......
...@@ -201,7 +201,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget { ...@@ -201,7 +201,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
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);
}); }, debugLabel: 'AutocompleteOptions.ensureVisible');
} }
return Container( return Container(
color: highlight ? Theme.of(context).focusColor : null, color: highlight ? Theme.of(context).focusColor : null,
......
...@@ -423,7 +423,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> { ...@@ -423,7 +423,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
setState(() { setState(() {
leadingPadding = getWidth(_leadingKey); leadingPadding = getWidth(_leadingKey);
}); });
}); }, debugLabel: 'DropdownMenu.refreshLeadingPadding');
} }
void scrollToHighlight() { void scrollToHighlight() {
...@@ -432,7 +432,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> { ...@@ -432,7 +432,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
if (highlightContext != null) { if (highlightContext != null) {
Scrollable.ensureVisible(highlightContext); Scrollable.ensureVisible(highlightContext);
} }
}); }, debugLabel: 'DropdownMenu.scrollToHighlight');
} }
double? getWidth(GlobalKey key) { double? getWidth(GlobalKey key) {
......
...@@ -174,7 +174,7 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> { ...@@ -174,7 +174,7 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
_selectedDate = widget.initialDate; _selectedDate = widget.initialDate;
_updateValueForSelectedDate(); _updateValueForSelectedDate();
}); });
}); }, debugLabel: 'InputDatePickerFormField.update');
} }
} }
......
...@@ -583,7 +583,7 @@ _MenuAnchorState? get _previousFocusableSibling { ...@@ -583,7 +583,7 @@ _MenuAnchorState? get _previousFocusableSibling {
} else if (!inDispose) { } else if (!inDispose) {
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
_overlayController.hide(); _overlayController.hide();
}); }, debugLabel: 'MenuAnchor.hide');
} }
if (!inDispose) { if (!inDispose) {
// Notify that _childIsOpen changed state, but only if not // Notify that _childIsOpen changed state, but only if not
...@@ -1150,7 +1150,7 @@ class _MenuItemButtonState extends State<MenuItemButton> { ...@@ -1150,7 +1150,7 @@ class _MenuItemButtonState extends State<MenuItemButton> {
SchedulerBinding.instance.addPostFrameCallback((Duration _) { SchedulerBinding.instance.addPostFrameCallback((Duration _) {
FocusManager.instance.applyFocusChangesIfNeeded(); FocusManager.instance.applyFocusChangesIfNeeded();
widget.onPressed?.call(); widget.onPressed?.call();
}); }, debugLabel: 'MenuAnchor.onPressed');
} }
void _createInternalFocusNodeIfNeeded() { void _createInternalFocusNodeIfNeeded() {
...@@ -1902,7 +1902,7 @@ class _SubmenuButtonState extends State<SubmenuButton> { ...@@ -1902,7 +1902,7 @@ class _SubmenuButtonState extends State<SubmenuButton> {
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
_menuController._anchor?._focusButton(); _menuController._anchor?._focusButton();
_waitingToFocusMenu = false; _waitingToFocusMenu = false;
}); }, debugLabel: 'MenuAnchor.focus');
_waitingToFocusMenu = true; _waitingToFocusMenu = true;
} }
setState(() { /* Rebuild with updated controller.isOpen value */ }); setState(() { /* Rebuild with updated controller.isOpen value */ });
......
...@@ -142,7 +142,7 @@ class SpellCheckSuggestionsToolbar extends StatelessWidget { ...@@ -142,7 +142,7 @@ class SpellCheckSuggestionsToolbar extends StatelessWidget {
if (editableTextState.mounted) { if (editableTextState.mounted) {
editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent); editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent);
} }
}); }, debugLabel: 'SpellCheckerSuggestionsToolbar.bringIntoView');
editableTextState.hideToolbar(); editableTextState.hideToolbar();
} }
......
...@@ -1507,7 +1507,7 @@ class _TabBarState extends State<TabBar> { ...@@ -1507,7 +1507,7 @@ class _TabBarState extends State<TabBar> {
} }
return true; return true;
}()); }());
}); }, debugLabel: 'TabBar.tabsCountCheck');
_debugHasScheduledValidTabsCountCheck = true; _debugHasScheduledValidTabsCountCheck = true;
return true; return true;
} }
...@@ -2024,7 +2024,7 @@ class _TabBarViewState extends State<TabBarView> { ...@@ -2024,7 +2024,7 @@ class _TabBarViewState extends State<TabBarView> {
} }
return true; return true;
}()); }());
}); }, debugLabel: 'TabBarView.validChildrenCountCheck');
_debugHasScheduledValidChildrenCountCheck = true; _debugHasScheduledValidChildrenCountCheck = true;
return true; return true;
} }
......
...@@ -655,7 +655,7 @@ void paintImage({ ...@@ -655,7 +655,7 @@ void paintImage({
}, },
); );
_pendingImageSizeInfo = <String, ImageSizeInfo>{}; _pendingImageSizeInfo = <String, ImageSizeInfo>{};
}); }, debugLabel: 'paintImage.recordImageSizes');
} }
} }
......
...@@ -621,7 +621,7 @@ abstract class _CachedImageBase { ...@@ -621,7 +621,7 @@ abstract class _CachedImageBase {
assert(handle != null); assert(handle != null);
handle?.dispose(); handle?.dispose();
handle = null; handle = null;
}); }, debugLabel: 'CachedImage.disposeHandle');
} }
} }
......
...@@ -46,7 +46,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture ...@@ -46,7 +46,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
addPersistentFrameCallback(_handlePersistentFrameCallback); addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker(); initMouseTracker();
if (kIsWeb) { if (kIsWeb) {
addPostFrameCallback(_handleWebFirstFrame); addPostFrameCallback(_handleWebFirstFrame, debugLabel: 'RendererBinding.webFirstFrame');
} }
rootPipelineOwner.attach(_manifold); rootPipelineOwner.attach(_manifold);
} }
...@@ -463,7 +463,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture ...@@ -463,7 +463,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
return true; return true;
}()); }());
_mouseTracker!.updateAllDevices(); _mouseTracker!.updateAllDevices();
}); }, debugLabel: 'RendererBinding.mouseTrackerUpdate');
} }
int _firstFrameDeferredCount = 0; int _firstFrameDeferredCount = 0;
......
...@@ -2337,7 +2337,7 @@ class LayerLink { ...@@ -2337,7 +2337,7 @@ class LayerLink {
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_debugLeaderCheckScheduled = false; _debugLeaderCheckScheduled = false;
assert(_debugPreviousLeaders!.isEmpty); assert(_debugPreviousLeaders!.isEmpty);
}); }, debugLabel: 'LayerLink.leadersCleanUpCheck');
return true; return true;
}()); }());
} }
......
...@@ -202,7 +202,7 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -202,7 +202,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
// Schedule a new post frame callback. // Schedule a new post frame callback.
_setOffset(); _setOffset();
} }
}); }, debugLabel: 'RenderAndroidView.setOffset');
} }
@override @override
......
...@@ -765,6 +765,13 @@ mixin SchedulerBinding on BindingBase { ...@@ -765,6 +765,13 @@ mixin SchedulerBinding on BindingBase {
/// ///
/// Post-frame callbacks cannot be unregistered. They are called exactly once. /// Post-frame callbacks cannot be unregistered. They are called exactly once.
/// ///
/// In debug mode, if [debugTracePostFrameCallbacks] is set to true, then the
/// registered callback will show up in the timeline events chart, which can
/// be viewed in [DevTools](https://docs.flutter.dev/tools/devtools/overview).
/// In that case, the `debugLabel` argument specifies the name of the callback
/// as it will appear in the timeline. In profile and release builds,
/// post-frame are never traced, and the `debugLabel` argument is ignored.
///
/// See also: /// See also:
/// ///
/// * [scheduleFrameCallback], which registers a callback for the start of /// * [scheduleFrameCallback], which registers a callback for the start of
...@@ -772,7 +779,21 @@ mixin SchedulerBinding on BindingBase { ...@@ -772,7 +779,21 @@ mixin SchedulerBinding on BindingBase {
/// * [WidgetsBinding.drawFrame], which explains the phases of each frame /// * [WidgetsBinding.drawFrame], which explains the phases of each frame
/// for those apps that use Flutter widgets (and where post frame /// for those apps that use Flutter widgets (and where post frame
/// callbacks fit into those phases). /// callbacks fit into those phases).
void addPostFrameCallback(FrameCallback callback) { void addPostFrameCallback(FrameCallback callback, {String debugLabel = 'callback'}) {
assert(() {
if (debugTracePostFrameCallbacks) {
final FrameCallback originalCallback = callback;
callback = (Duration timeStamp) {
Timeline.startSync(debugLabel);
try {
originalCallback(timeStamp);
} finally {
Timeline.finishSync();
}
};
}
return true;
}());
_postFrameCallbacks.add(callback); _postFrameCallbacks.add(callback);
} }
...@@ -796,7 +817,7 @@ mixin SchedulerBinding on BindingBase { ...@@ -796,7 +817,7 @@ mixin SchedulerBinding on BindingBase {
addPostFrameCallback((Duration timeStamp) { addPostFrameCallback((Duration timeStamp) {
_nextFrameCompleter!.complete(); _nextFrameCompleter!.complete();
_nextFrameCompleter = null; _nextFrameCompleter = null;
}); }, debugLabel: 'SchedulerBinding.completeFrame');
} }
return _nextFrameCompleter!.future; return _nextFrameCompleter!.future;
} }
...@@ -1127,7 +1148,7 @@ mixin SchedulerBinding on BindingBase { ...@@ -1127,7 +1148,7 @@ mixin SchedulerBinding on BindingBase {
// still be true here and cause us to skip scheduling an engine frame. // still be true here and cause us to skip scheduling an engine frame.
_hasScheduledFrame = false; _hasScheduledFrame = false;
scheduleFrame(); scheduleFrame();
}); }, debugLabel: 'SchedulerBinding.scheduleFrame');
return; return;
} }
handleDrawFrame(); handleDrawFrame();
...@@ -1280,8 +1301,13 @@ mixin SchedulerBinding on BindingBase { ...@@ -1280,8 +1301,13 @@ mixin SchedulerBinding on BindingBase {
final List<FrameCallback> localPostFrameCallbacks = final List<FrameCallback> localPostFrameCallbacks =
List<FrameCallback>.of(_postFrameCallbacks); List<FrameCallback>.of(_postFrameCallbacks);
_postFrameCallbacks.clear(); _postFrameCallbacks.clear();
for (final FrameCallback callback in localPostFrameCallbacks) { Timeline.startSync('POST_FRAME');
_invokeFrameCallback(callback, _currentFrameTimeStamp!); try {
for (final FrameCallback callback in localPostFrameCallbacks) {
_invokeFrameCallback(callback, _currentFrameTimeStamp!);
}
} finally {
Timeline.finishSync();
} }
} finally { } finally {
_schedulerPhase = SchedulerPhase.idle; _schedulerPhase = SchedulerPhase.idle;
......
...@@ -48,6 +48,20 @@ bool debugPrintEndFrameBanner = false; ...@@ -48,6 +48,20 @@ bool debugPrintEndFrameBanner = false;
/// [debugPrintScheduleBuildForStacks]. /// [debugPrintScheduleBuildForStacks].
bool debugPrintScheduleFrameStacks = false; bool debugPrintScheduleFrameStacks = false;
/// Record timeline trace events for post-frame callbacks.
///
/// When this flag is set to false (the default), the developer timeline
/// records when post-frame callbacks are running, but it does not tell you any
/// information about how that time is spent within specific callbacks:
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/scheduler/debug_trace_post_frame_callbacks_off.png)
///
/// When this flag is set to true, timeline events will be recorded for each
/// post-frame callback that runs, like so:
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/scheduler/debug_trace_post_frame_callbacks_on.png)
bool debugTracePostFrameCallbacks = false;
/// Returns true if none of the scheduler library debug variables have been changed. /// Returns true if none of the scheduler library debug variables have been changed.
/// ///
/// This function is used by the test framework to ensure that debug variables /// This function is used by the test framework to ensure that debug variables
......
...@@ -268,7 +268,7 @@ class RestorationManager extends ChangeNotifier { ...@@ -268,7 +268,7 @@ class RestorationManager extends ChangeNotifier {
if (_isReplacing) { if (_isReplacing) {
SchedulerBinding.instance.addPostFrameCallback((Duration _) { SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_isReplacing = false; _isReplacing = false;
}); }, debugLabel: 'RestorationManager.resetIsReplacing');
} }
final RestorationBucket? oldRoot = _rootBucket; final RestorationBucket? oldRoot = _rootBucket;
...@@ -349,7 +349,10 @@ class RestorationManager extends ChangeNotifier { ...@@ -349,7 +349,10 @@ 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(),
debugLabel: 'RestorationManager.doSerialization'
);
} }
} }
......
...@@ -1231,7 +1231,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> { ...@@ -1231,7 +1231,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
super.initState(); super.initState();
SchedulerBinding.instance.addPostFrameCallback((Duration duration) { SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
_updateHighlightMode(FocusManager.instance.highlightMode); _updateHighlightMode(FocusManager.instance.highlightMode);
}); }, debugLabel: 'FocusableActionDetector.updateHighlightMode');
FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange); FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange);
} }
...@@ -1339,7 +1339,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> { ...@@ -1339,7 +1339,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
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);
}); }, debugLabel: 'FocusableActionDetector.mayTriggerCallback');
} }
} }
......
...@@ -440,7 +440,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>> ...@@ -440,7 +440,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_floatingOptionsUpdateScheduled = false; _floatingOptionsUpdateScheduled = false;
_updateOverlay(); _updateOverlay();
}); }, debugLabel: 'RawAutoComplete.updateOverlay');
} }
return; return;
} }
......
...@@ -99,7 +99,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> { ...@@ -99,7 +99,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement(); final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
assert(childElement != null); assert(childElement != null);
_updateParentDataOfChild(childElement!); _updateParentDataOfChild(childElement!);
}); }, debugLabel: 'AutomaticKeepAlive.updateParentData');
} }
} }
return false; return false;
......
...@@ -763,7 +763,7 @@ class _DraggableScrollableSheetState extends State<DraggableScrollableSheet> { ...@@ -763,7 +763,7 @@ class _DraggableScrollableSheetState extends State<DraggableScrollableSheet> {
_scrollController.positions.elementAt(index) as _DraggableScrollableSheetScrollPosition; _scrollController.positions.elementAt(index) as _DraggableScrollableSheetScrollPosition;
position.goBallistic(0); position.goBallistic(0);
} }
}); }, debugLabel: 'DraggableScrollableSheet.snap');
} }
} }
......
...@@ -2390,7 +2390,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2390,7 +2390,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (mounted) { if (mounted) {
bringIntoView(textEditingValue.selection.extent); bringIntoView(textEditingValue.selection.extent);
} }
}); }, debugLabel: 'EditableText.bringSelectionIntoView');
hideToolbar(); hideToolbar();
} }
clipboardStatus.update(); clipboardStatus.update();
...@@ -2430,7 +2430,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2430,7 +2430,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (mounted) { if (mounted) {
bringIntoView(textEditingValue.selection.extent); bringIntoView(textEditingValue.selection.extent);
} }
}); }, debugLabel: 'EditableText.bringSelectionIntoView');
hideToolbar(); hideToolbar();
} }
} }
...@@ -2818,7 +2818,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2818,7 +2818,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_flagInternalFocus(); _flagInternalFocus();
FocusScope.of(context).autofocus(widget.focusNode); FocusScope.of(context).autofocus(widget.focusNode);
} }
}); }, debugLabel: 'EditableText.autofocus');
} }
// Restart or stop the blinking cursor when TickerMode changes. // Restart or stop the blinking cursor when TickerMode changes.
...@@ -2889,7 +2889,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2889,7 +2889,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
// See https://github.com/flutter/flutter/issues/126312 // See https://github.com/flutter/flutter/issues/126312
SchedulerBinding.instance.addPostFrameCallback((Duration _) { SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_openInputConnection(); _openInputConnection();
}); }, debugLabel: 'EditableText.openInputConnection');
} }
if (kIsWeb && _hasInputConnection) { if (kIsWeb && _hasInputConnection) {
...@@ -3721,7 +3721,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3721,7 +3721,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
rect: caretPadding.inflateRect(rectToReveal), rect: caretPadding.inflateRect(rectToReveal),
); );
} }
}); }, debugLabel: 'EditableText.showCaret');
} }
late double _lastBottomViewInset; late double _lastBottomViewInset;
...@@ -3735,7 +3735,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3735,7 +3735,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (_lastBottomViewInset != view.viewInsets.bottom) { if (_lastBottomViewInset != view.viewInsets.bottom) {
SchedulerBinding.instance.addPostFrameCallback((Duration _) { SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_selectionOverlay?.updateForScroll(); _selectionOverlay?.updateForScroll();
}); }, debugLabel: 'EditableText.updateForScroll');
if (_lastBottomViewInset < view.viewInsets.bottom) { if (_lastBottomViewInset < view.viewInsets.bottom) {
// Because the metrics change signal from engine will come here every frame // Because the metrics change signal from engine will come here every frame
// (on both iOS and Android). So we don't need to show caret with animation. // (on both iOS and Android). So we don't need to show caret with animation.
...@@ -4038,7 +4038,10 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -4038,7 +4038,10 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_updateSelectionRects(); _updateSelectionRects();
_updateComposingRectIfNeeded(); _updateComposingRectIfNeeded();
_updateCaretRectIfNeeded(); _updateCaretRectIfNeeded();
SchedulerBinding.instance.addPostFrameCallback(_schedulePeriodicPostFrameCallbacks); SchedulerBinding.instance.addPostFrameCallback(
_schedulePeriodicPostFrameCallbacks,
debugLabel: 'EditableText.postFrameCallbacks'
);
} }
_ScribbleCacheKey? _scribbleCacheKey; _ScribbleCacheKey? _scribbleCacheKey;
......
...@@ -902,7 +902,7 @@ class HeroController extends NavigatorObserver { ...@@ -902,7 +902,7 @@ class HeroController extends NavigatorObserver {
return; return;
} }
_startHeroTransition(from, to, flightType, isUserGestureTransition); _startHeroTransition(from, to, flightType, isUserGestureTransition);
}); }, debugLabel: 'HeroController.startTransition');
} }
} }
......
...@@ -124,7 +124,7 @@ Future<void> precacheImage( ...@@ -124,7 +124,7 @@ Future<void> precacheImage(
// See ImageCache._liveImages // See ImageCache._liveImages
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
stream.removeListener(listener!); stream.removeListener(listener!);
}); }, debugLabel: 'precacheImage.removeListener');
}, },
onError: (Object exception, StackTrace? stackTrace) { onError: (Object exception, StackTrace? stackTrace) {
if (!completer.isCompleted) { if (!completer.isCompleted) {
...@@ -1164,7 +1164,10 @@ class _ImageState extends State<Image> with WidgetsBindingObserver { ...@@ -1164,7 +1164,10 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
void _replaceImage({required ImageInfo? info}) { void _replaceImage({required ImageInfo? info}) {
final ImageInfo? oldImageInfo = _imageInfo; final ImageInfo? oldImageInfo = _imageInfo;
SchedulerBinding.instance.addPostFrameCallback((_) => oldImageInfo?.dispose()); SchedulerBinding.instance.addPostFrameCallback(
(_) => oldImageInfo?.dispose(),
debugLabel: 'Image.disposeOldInfo'
);
_imageInfo = info; _imageInfo = info;
} }
......
...@@ -3509,7 +3509,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res ...@@ -3509,7 +3509,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
return; return;
} }
notification.dispatch(context); notification.dispatch(context);
}); }, debugLabel: 'Navigator.dispatchNotification');
} }
} }
...@@ -3716,7 +3716,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res ...@@ -3716,7 +3716,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
); );
} }
} }
}); }, debugLabel: 'Navigator.checkHeroControllerOwnership');
} }
return true; return true;
}()); }());
......
...@@ -1183,11 +1183,9 @@ class _NestedScrollController extends ScrollController { ...@@ -1183,11 +1183,9 @@ 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(); }, debugLabel: 'NestedScrollController.updateShadow');
},
);
} }
Iterable<_NestedScrollPosition> get nestedPositions { Iterable<_NestedScrollPosition> get nestedPositions {
......
...@@ -177,7 +177,7 @@ class OverlayEntry implements Listenable { ...@@ -177,7 +177,7 @@ class OverlayEntry implements Listenable {
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();
}); }, debugLabel: 'OverlayEntry.markDirty');
} else { } else {
overlay._markDirty(); overlay._markDirty();
} }
......
...@@ -1301,7 +1301,7 @@ class _PlatformViewPlaceholderBox extends RenderConstrainedBox { ...@@ -1301,7 +1301,7 @@ class _PlatformViewPlaceholderBox extends RenderConstrainedBox {
// A call to `localToGlobal` requires waiting for a frame to render first. // A call to `localToGlobal` requires waiting for a frame to render first.
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
onLayout(size, localToGlobal(Offset.zero)); onLayout(size, localToGlobal(Offset.zero));
}); }, debugLabel: 'PlatformViewPlaceholderBox.onLayout');
} }
} }
...@@ -1333,6 +1333,6 @@ extension on PlatformViewController { ...@@ -1333,6 +1333,6 @@ extension on PlatformViewController {
void disposePostFrame() { void disposePostFrame() {
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
dispose(); dispose();
}); }, debugLabel: 'PlatformViewController.dispose');
} }
} }
...@@ -753,7 +753,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke ...@@ -753,7 +753,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
_dragStartTransitionComplete = false; _dragStartTransitionComplete = false;
SchedulerBinding.instance.addPostFrameCallback((Duration duration) { SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
_dragStartTransitionComplete = true; _dragStartTransitionComplete = true;
}); }, debugLabel: 'SliverReorderableList.completeDragStartTransition');
_insertIndex = item.index; _insertIndex = item.index;
_dragInfo = _DragInfo( _dragInfo = _DragInfo(
......
...@@ -628,7 +628,10 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin { ...@@ -628,7 +628,10 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
} }
assert(_currentIntentionToReport != null); assert(_currentIntentionToReport != null);
_routeInformationReportingTaskScheduled = true; _routeInformationReportingTaskScheduled = true;
SchedulerBinding.instance.addPostFrameCallback(_reportRouteInformation); SchedulerBinding.instance.addPostFrameCallback(
_reportRouteInformation,
debugLabel: 'Router.reportRouteInfo',
);
} }
void _reportRouteInformation(Duration timestamp) { void _reportRouteInformation(Duration timestamp) {
......
...@@ -710,7 +710,7 @@ mixin LocalHistoryRoute<T> on Route<T> { ...@@ -710,7 +710,7 @@ mixin LocalHistoryRoute<T> on Route<T> {
if (isActive) { if (isActive) {
changedInternalState(); changedInternalState();
} }
}); }, debugLabel: 'LocalHistoryRoute.changedInternalState');
} else { } else {
changedInternalState(); changedInternalState();
} }
...@@ -1672,7 +1672,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -1672,7 +1672,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
return; return;
} }
notification.dispatch(subtreeContext); notification.dispatch(subtreeContext);
}); }, debugLabel: 'ModalRoute.dispatchNotification');
} }
} }
......
...@@ -468,7 +468,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics { ...@@ -468,7 +468,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
notifyListeners(); notifyListeners();
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_impliedVelocity = 0; _impliedVelocity = 0;
}); }, debugLabel: 'ScrollPosition.resetVelocity');
} }
/// Called whenever scrolling ends, to store the current scroll offset in a /// Called whenever scrolling ends, to store the current scroll offset in a
......
...@@ -1167,7 +1167,7 @@ class _ScrollableSelectionContainerDelegate extends MultiSelectableSelectionCont ...@@ -1167,7 +1167,7 @@ class _ScrollableSelectionContainerDelegate extends MultiSelectableSelectionCont
} }
_scheduledLayoutChange = false; _scheduledLayoutChange = false;
layoutDidChange(); layoutDidChange();
}); }, debugLabel: 'ScrollableSelectionContainer.layoutDidChange');
} }
/// Stores the scroll offset when a scrollable receives the last /// Stores the scroll offset when a scrollable receives the last
......
...@@ -1413,7 +1413,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv ...@@ -1413,7 +1413,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
} }
WidgetsBinding.instance.addPostFrameCallback((Duration duration) { WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
assert(_debugCheckHasValidScrollPosition()); assert(_debugCheckHasValidScrollPosition());
}); }, debugLabel: 'RawScrollbar.checkScrollPosition');
return true; return true;
} }
......
...@@ -677,7 +677,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe ...@@ -677,7 +677,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe
} }
_scheduledSelectionEndEdgeUpdate = false; _scheduledSelectionEndEdgeUpdate = false;
_triggerSelectionEndEdgeUpdate(textGranularity: textGranularity); _triggerSelectionEndEdgeUpdate(textGranularity: textGranularity);
}); }, debugLabel: 'SelectableRegion.endEdgeUpdate');
return; return;
} }
} }
...@@ -731,7 +731,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe ...@@ -731,7 +731,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe
} }
_scheduledSelectionStartEdgeUpdate = false; _scheduledSelectionStartEdgeUpdate = false;
_triggerSelectionStartEdgeUpdate(textGranularity: textGranularity); _triggerSelectionStartEdgeUpdate(textGranularity: textGranularity);
}); }, debugLabel: 'SelectableRegion.startEdgeUpdate');
return; return;
} }
} }
...@@ -1716,7 +1716,10 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai ...@@ -1716,7 +1716,10 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai
// safely updated in the same frame in this case. // safely updated in the same frame in this case.
scheduleMicrotask(runScheduledTask); scheduleMicrotask(runScheduledTask);
} else { } else {
SchedulerBinding.instance.addPostFrameCallback(runScheduledTask); SchedulerBinding.instance.addPostFrameCallback(
runScheduledTask,
debugLabel: 'SelectionContainer.runScheduledTask',
);
} }
} }
} }
......
...@@ -94,7 +94,7 @@ class _SemanticsDebuggerState extends State<SemanticsDebugger> with WidgetsBindi ...@@ -94,7 +94,7 @@ class _SemanticsDebuggerState extends State<SemanticsDebugger> with WidgetsBindi
// The generation of the _SemanticsDebuggerListener has changed. // The generation of the _SemanticsDebuggerListener has changed.
}); });
} }
}); }, debugLabel: 'SemanticsDebugger.update');
} }
Offset? _lastPointerDownLocation; Offset? _lastPointerDownLocation;
......
...@@ -1276,7 +1276,7 @@ class ShortcutRegistry with ChangeNotifier { ...@@ -1276,7 +1276,7 @@ class ShortcutRegistry with ChangeNotifier {
if (!_disposed) { if (!_disposed) {
notifyListeners(); notifyListeners();
} }
}); }, debugLabel: 'ShortcutRegistry.notifyListeners');
_notificationScheduled = true; _notificationScheduled = true;
} }
} }
......
...@@ -1454,7 +1454,7 @@ class SelectionOverlay { ...@@ -1454,7 +1454,7 @@ class SelectionOverlay {
} else if (_spellCheckToolbarController.isShown) { } else if (_spellCheckToolbarController.isShown) {
_spellCheckToolbarController.markNeedsBuild(); _spellCheckToolbarController.markNeedsBuild();
} }
}); }, debugLabel: 'SelectionOverlay.markNeedsBuild');
} else { } else {
if (_handles != null) { if (_handles != null) {
_handles!.start.markNeedsBuild(); _handles!.start.markNeedsBuild();
......
...@@ -2371,7 +2371,7 @@ mixin WidgetInspectorService { ...@@ -2371,7 +2371,7 @@ mixin WidgetInspectorService {
void _onFrameStart(Duration timeStamp) { void _onFrameStart(Duration timeStamp) {
_frameStart = timeStamp; _frameStart = timeStamp;
SchedulerBinding.instance.addPostFrameCallback(_onFrameEnd); SchedulerBinding.instance.addPostFrameCallback(_onFrameEnd, debugLabel: 'WidgetInspector.onFrameStart');
} }
void _onFrameEnd(Duration timeStamp) { void _onFrameEnd(Duration timeStamp) {
......
...@@ -33,7 +33,7 @@ class TestResampleEventFlutterBinding extends BindingBase with GestureBinding, S ...@@ -33,7 +33,7 @@ class TestResampleEventFlutterBinding extends BindingBase with GestureBinding, S
} }
@override @override
int addPostFrameCallback(FrameCallback callback) { int addPostFrameCallback(FrameCallback callback, {String debugLabel = 'callback'}) {
postFrameCallback = callback; postFrameCallback = callback;
return 0; return 0;
} }
......
...@@ -70,7 +70,7 @@ class TestMouseTrackerFlutterBinding extends BindingBase ...@@ -70,7 +70,7 @@ class TestMouseTrackerFlutterBinding extends BindingBase
// Proxy post-frame callbacks. // Proxy post-frame callbacks.
@override @override
void addPostFrameCallback(void Function(Duration) callback) { void addPostFrameCallback(void Function(Duration) callback, {String debugLabel = 'callback'}) {
postFrameCallbacks.add(callback); postFrameCallbacks.add(callback);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment