Unverified Commit 89907f6d authored by Polina Cherkasova's avatar Polina Cherkasova Committed by GitHub

Enable ChangeNotifier clients to dispatch event of object creation in constructor. (#133060)

parent 382ceb57
......@@ -207,6 +207,39 @@ mixin class ChangeNotifier implements Listenable {
@protected
bool get hasListeners => _count > 0;
/// Dispatches event of object creation to [MemoryAllocations.instance].
///
/// If the event was already dispatched or [kFlutterMemoryAllocationsEnabled]
/// is false, the method is noop.
///
/// Tools like leak_tracker use the event of object creation to help
/// developers identify the owner of the object, for troubleshooting purposes,
/// by taking stack trace at the moment of the event.
///
/// But, as [ChangeNotifier] is mixin, it does not have its own constructor. So, it
/// communicates object creation in first `addListener`, that results
/// in the stack trace pointing to `addListener`, not to constructor.
///
/// To make debugging easier, invoke [ChangeNotifier.maybeDispatchObjectCreation]
/// in constructor of the class. It will help
/// to identify the owner.
///
/// Make sure to invoke it with condition `if (kFlutterMemoryAllocationsEnabled) ...`
/// so that the method is tree-shaken away when the flag is false.
@protected
void maybeDispatchObjectCreation() {
// Tree shaker does not include this method and the class MemoryAllocations
// if kFlutterMemoryAllocationsEnabled is false.
if (kFlutterMemoryAllocationsEnabled && !_creationDispatched) {
MemoryAllocations.instance.dispatchObjectCreated(
library: _flutterFoundationLibrary,
className: '$ChangeNotifier',
object: this,
);
_creationDispatched = true;
}
}
/// Register a closure to be called when the object changes.
///
/// If the given closure is already registered, an additional instance is
......@@ -236,14 +269,11 @@ mixin class ChangeNotifier implements Listenable {
@override
void addListener(VoidCallback listener) {
assert(ChangeNotifier.debugAssertNotDisposed(this));
if (kFlutterMemoryAllocationsEnabled && !_creationDispatched) {
MemoryAllocations.instance.dispatchObjectCreated(
library: _flutterFoundationLibrary,
className: '$ChangeNotifier',
object: this,
);
_creationDispatched = true;
if (kFlutterMemoryAllocationsEnabled) {
maybeDispatchObjectCreation();
}
if (_count == _listeners.length) {
if (_count == 0) {
_listeners = List<VoidCallback?>.filled(1, null);
......@@ -505,13 +535,8 @@ class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {
/// Creates a [ChangeNotifier] that wraps this value.
ValueNotifier(this._value) {
if (kFlutterMemoryAllocationsEnabled) {
MemoryAllocations.instance.dispatchObjectCreated(
library: _flutterFoundationLibrary,
className: '$ValueNotifier',
object: this,
);
maybeDispatchObjectCreation();
}
_creationDispatched = true;
}
/// The current value stored in this notifier.
......
......@@ -1196,6 +1196,13 @@ class ShortcutRegistryEntry {
/// widgets that are not descendants of the registry can listen to it (e.g. in
/// overlays).
class ShortcutRegistry with ChangeNotifier {
/// Creates an instance of [ShortcutRegistry].
ShortcutRegistry() {
if (kFlutterMemoryAllocationsEnabled) {
maybeDispatchObjectCreation();
}
}
bool _notificationScheduled = false;
bool _disposed = false;
......
......@@ -482,4 +482,8 @@ class _DefaultSnapshotPainter implements SnapshotPainter {
@override
bool shouldRepaint(covariant _DefaultSnapshotPainter oldPainter) => false;
@override
@protected
void maybeDispatchObjectCreation() { }
}
......@@ -1852,6 +1852,22 @@ void main() {
}, throwsAssertionError);
token.dispose();
});
testWidgets('dispatches object creation in constructor', (WidgetTester tester) async {
final MemoryAllocations ma = MemoryAllocations.instance;
assert(!ma.hasListeners);
int eventCount = 0;
void listener(ObjectEvent event) => eventCount++;
ma.addListener(listener);
final ShortcutRegistry registry = ShortcutRegistry();
expect(eventCount, 1);
registry.dispose();
ma.removeListener(listener);
assert(!ma.hasListeners);
});
});
}
......
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