-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Allow multiple TimingsCallbacks #43676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This fixes flutter#39277
5733255 to
1e9582c
Compare
| // TODO(liyuqian): once this is merged, modify the doc of | ||
| // [Window.onReportTimings] inside the engine repo to recommend using this | ||
| // API instead of using [Window.onReportTimings] directly. | ||
| _timingsCallbacksEnabled[callback] = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I add the same callback twice it will only get called once? That's probably expected, but might be worth documenting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've modified it to use a list so now it actually gets called twice. Documented such behavior too.
| assert(window.onReportTimings == null); | ||
| window.onReportTimings = (List<FrameTiming> timings) { | ||
| for (TimingsCallback callback in _timingsCallbacks) { | ||
| callback(timings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if callback removes itself from _timingsCallbacks? You probably want to iterate over a copy of _timingsCallbacks to avoid problems (_timingsCallbacks.toList() should work).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original map was for that. But I've changed it the the cloned list approach as you suggested. I was trying to save some copying time but I guess the saving isn't worth the confusion.
| /// Removes a callback that was earlier added by [addTimingsCallback]. | ||
| void removeTimingsCallback(TimingsCallback callback) { | ||
| assert(_timingsCallbacksEnabled.containsKey(callback)); | ||
| _timingsCallbacksEnabled[callback] = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you keep track of whats enabled/disabled? Why not just remove it?
It also looks like this Map never gets cleaned up and the callback (and all the resources closured in to it) will be held in memory indefinitely. That seems like a leak?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to list and removed the calllback when needed.
|
|
||
| void _executeTimingsCallbacks(List<FrameTiming> timings) { | ||
| final List<TimingsCallback> clonedCallbacks = | ||
| List<TimingsCallback>.from(_timingsCallbacks); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: either indent further or move to previous line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this! I thought I indented by somehow it's missing...
| final List<TimingsCallback> clonedCallbacks = | ||
| List<TimingsCallback>.from(_timingsCallbacks); | ||
| for (TimingsCallback callback in clonedCallbacks) { | ||
| callback(timings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other places where we have similar code we check here if the callback is still in clonedCallbacks, for example:
flutter/packages/flutter/lib/src/foundation/change_notifier.dart
Lines 205 to 206 in b31ca1a
| if (_listeners.contains(listener)) | |
| listener(); |
That way if your list is [callbackA, callbackB] and callbackA removes callbackB, callbackB is not called again. This would probably also make sense here?
Also from that link: Should we catch exceptions here that happen while executing callback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Also added a test for the error handling.
| } | ||
| } | ||
|
|
||
| final List<TimingsCallback> _timingsCallbacks = <TimingsCallback>[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would move this field up above addTimingsCallback, but that's probably up to personal taste.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
goderbauer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This fixes flutter#39277 The following tests cover this change: - packages/flutter/test/foundation/service_extensions_test.dart - packages/flutter/test/scheduler/scheduler_test.dart
This fixes #39277
The following tests cover this change: