defaultNotifyListeners method
Notify all the listeners.
eventThe event to send to the listeners.
Implementation
@protected
@visibleForTesting
@pragma('vm:notify-debugger-on-exception')
void defaultNotifyListeners(Object? event) {
assert(debugAssertNotDisposed(this));
if (_count == 0) {
return;
}
// To make sure that listeners removed during this iteration are not called,
// we set them to null, but we don't shrink the list right away.
// By doing this, we can continue to iterate on our list until it reaches
// the last listener added before the call to this method.
// To allow potential listeners to recursively call notifyListener, we track
// the number of times this method is called in _notificationCallStackDepth.
// Once every recursive iteration is finished (i.e. when _notificationCallStackDepth == 0),
// we can safely shrink our list so that it will only contain not null
// listeners.
_notificationCallStackDepth++;
final int end = _count;
for (int i = 0; i < end; i++) {
try {
final ChangeListener? listener = _listeners[i];
if (listener != null) {
listener.dispatch(event);
}
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: _kDataWidgetLibrary,
context: ErrorDescription(
'while dispatching notifications for $runtimeType'),
informationCollector: () => <DiagnosticsNode>[
DiagnosticsProperty<ChangesNotifierHelperMixin>(
'The $runtimeType sending notification was',
this,
style: DiagnosticsTreeStyle.errorProperty,
),
],
));
}
}
_notificationCallStackDepth--;
if (_notificationCallStackDepth == 0 && _reentrantlyRemovedListeners > 0) {
// We really remove the listeners when all notifications are done.
final int newLength = _count - _reentrantlyRemovedListeners;
if (newLength * 2 <= _listeners.length) {
// As in _removeAt, we only shrink the list when the real number of
// listeners is half the length of our list.
final List<ChangeListener?> newListeners =
List<ChangeListener?>.filled(newLength, null);
int newIndex = 0;
for (int i = 0; i < _count; i++) {
final listener = _listeners[i];
if (listener != null) {
newListeners[newIndex++] = listener;
}
}
_listeners = newListeners;
} else {
// Otherwise we put all the null references at the end.
for (int i = 0; i < newLength; i += 1) {
if (_listeners[i] == null) {
// We swap this item with the next not null item.
int swapIndex = i + 1;
while (_listeners[swapIndex] == null) {
swapIndex += 1;
}
_listeners[i] = _listeners[swapIndex];
_listeners[swapIndex] = null;
}
}
}
_reentrantlyRemovedListeners = 0;
_count = newLength;
}
}