change_notifier.dart 2.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:meta/meta.dart';

import 'assertions.dart';
import 'basic_types.dart';

/// Abstract class that can be extended or mixed in that provides
/// a change notification API using [VoidCallback] for notifications.
abstract class ChangeNotifier {
  List<VoidCallback> _listeners;

  /// Register a closure to be called when the object changes.
  void addListener(VoidCallback listener) {
    _listeners ??= <VoidCallback>[];
    _listeners.add(listener);
  }

  /// Remove a previously registered closure from the list of closures that are
  /// notified when the object changes.
  void removeListener(VoidCallback listener) {
    _listeners?.remove(listener);
  }

  /// Discards any resources used by the object. After this is called, the object
  /// is not in a usable state and should be discarded.
  ///
  /// This method should only be called by the object's owner.
  @mustCallSuper
  void dispose() {
33
    _listeners = const <VoidCallback>[];
34 35 36 37 38
  }

  /// Call all the registered listeners.
  ///
  /// Call this method whenever the object changes, to notify any clients the
39 40 41
  /// object may have. Listeners that are added during this iteration will not
  /// be visited. Listeners that are removed during this iteration will not be
  /// visited after they are removed.
42 43 44 45 46 47
  ///
  /// Exceptions thrown by listeners will be caught and reported using
  /// [FlutterError.reportError].
  @protected
  void notifyListeners() {
    if (_listeners != null) {
48 49
      List<VoidCallback> localListeners = new List<VoidCallback>.from(_listeners);
      for (VoidCallback listener in localListeners) {
50
        try {
51 52
          if (_listeners.contains(listener))
            listener();
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
        } catch (exception, stack) {
          FlutterError.reportError(new FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'foundation library',
            context: 'while dispatching notifications for $runtimeType',
            informationCollector: (StringBuffer information) {
              information.writeln('The $runtimeType sending notification was:');
              information.write('  $this');
            }
          ));
        }
      }
    }
  }
}