| 
 | 1 | +// Copyright 2014 The Flutter Authors. All rights reserved.  | 
 | 2 | +// Use of this source code is governed by a BSD-style license that can be  | 
 | 3 | +// found in the LICENSE file.  | 
 | 4 | + | 
 | 5 | +/// An object that maintains a list of listeners.  | 
 | 6 | +///  | 
 | 7 | +/// The listeners are typically used to notify clients that the object has been  | 
 | 8 | +/// updated.  | 
 | 9 | +///  | 
 | 10 | +/// There are two variants of this interface:  | 
 | 11 | +///  | 
 | 12 | +///  * [ValueListenable], an interface that augments the [Listenable] interface  | 
 | 13 | +///    with the concept of a _current value_.  | 
 | 14 | +///  | 
 | 15 | +///  * [Animation], an interface that augments the [ValueListenable] interface  | 
 | 16 | +///    to add the concept of direction (forward or reverse).  | 
 | 17 | +///  | 
 | 18 | +/// Many classes in the Flutter API use or implement these interfaces. The  | 
 | 19 | +/// following subclasses are especially relevant:  | 
 | 20 | +///  | 
 | 21 | +///  * [ChangeNotifier], which can be subclassed or mixed in to create objects  | 
 | 22 | +///    that implement the [Listenable] interface.  | 
 | 23 | +///  | 
 | 24 | +///  * [ValueNotifier], which implements the [ValueListenable] interface with  | 
 | 25 | +///    a mutable value that triggers the notifications when modified.  | 
 | 26 | +///  | 
 | 27 | +/// The terms "notify clients", "send notifications", "trigger notifications",  | 
 | 28 | +/// and "fire notifications" are used interchangeably.  | 
 | 29 | +///  | 
 | 30 | +/// See also:  | 
 | 31 | +///  | 
 | 32 | +///  * [AnimatedBuilder], a widget that uses a builder callback to rebuild  | 
 | 33 | +///    whenever a given [Listenable] triggers its notifications. This widget is  | 
 | 34 | +///    commonly used with [Animation] subclasses, hence its name, but is by no  | 
 | 35 | +///    means limited to animations, as it can be used with any [Listenable]. It  | 
 | 36 | +///    is a subclass of [AnimatedWidget], which can be used to create widgets  | 
 | 37 | +///    that are driven from a [Listenable].  | 
 | 38 | +///  * [ValueListenableBuilder], a widget that uses a builder callback to  | 
 | 39 | +///    rebuild whenever a [ValueListenable] object triggers its notifications,  | 
 | 40 | +///    providing the builder with the value of the object.  | 
 | 41 | +///  * [InheritedNotifier], an abstract superclass for widgets that use a  | 
 | 42 | +///    [Listenable]'s notifications to trigger rebuilds in descendant widgets  | 
 | 43 | +///    that declare a dependency on them, using the [InheritedWidget] mechanism.  | 
 | 44 | +///  * [Listenable.merge], which creates a [Listenable] that triggers  | 
 | 45 | +///    notifications whenever any of a list of other [Listenable]s trigger their  | 
 | 46 | +///    notifications.  | 
 | 47 | +abstract class Listenable {  | 
 | 48 | +  /// Abstract const constructor. This constructor enables subclasses to provide  | 
 | 49 | +  /// const constructors so that they can be used in const expressions.  | 
 | 50 | +  const Listenable();  | 
 | 51 | + | 
 | 52 | +  /// Return a [Listenable] that triggers when any of the given [Listenable]s  | 
 | 53 | +  /// themselves trigger.  | 
 | 54 | +  ///  | 
 | 55 | +  /// Once the factory is called, items must not be added or removed from the  | 
 | 56 | +  /// iterable.  | 
 | 57 | +  /// Doing so will lead to memory leaks or exceptions.  | 
 | 58 | +  ///  | 
 | 59 | +  /// The iterable may contain nulls; they are ignored.  | 
 | 60 | +  factory Listenable.merge(Iterable<Listenable?> listenables) =  | 
 | 61 | +      _MergingListenable;  | 
 | 62 | + | 
 | 63 | +  /// Register a closure to be called when the object notifies its listeners.  | 
 | 64 | +  void addListener(void Function() listener);  | 
 | 65 | + | 
 | 66 | +  /// Remove a previously registered closure from the list of closures that the  | 
 | 67 | +  /// object notifies.  | 
 | 68 | +  void removeListener(void Function() listener);  | 
 | 69 | +}  | 
 | 70 | + | 
 | 71 | +/// An interface for subclasses of [Listenable] that expose a [value].  | 
 | 72 | +///  | 
 | 73 | +/// This interface is implemented by [ValueNotifier<T>] and [Animation<T>], and  | 
 | 74 | +/// allows other APIs to accept either of those implementations interchangeably.  | 
 | 75 | +///  | 
 | 76 | +/// See also:  | 
 | 77 | +///  | 
 | 78 | +///  * [ValueListenableBuilder], a widget that uses a builder callback to  | 
 | 79 | +///    rebuild whenever a [ValueListenable] object triggers its notifications,  | 
 | 80 | +///    providing the builder with the value of the object.  | 
 | 81 | +abstract class ValueListenable<T> extends Listenable {  | 
 | 82 | +  /// Abstract const constructor. This constructor enables subclasses to provide  | 
 | 83 | +  /// const constructors so that they can be used in const expressions.  | 
 | 84 | +  const ValueListenable();  | 
 | 85 | + | 
 | 86 | +  /// The current value of the object. When the value changes, the callbacks  | 
 | 87 | +  /// registered with [addListener] will be invoked.  | 
 | 88 | +  T get value;  | 
 | 89 | +}  | 
 | 90 | + | 
 | 91 | +class _MergingListenable extends Listenable {  | 
 | 92 | +  _MergingListenable(this._children);  | 
 | 93 | + | 
 | 94 | +  final Iterable<Listenable?> _children;  | 
 | 95 | + | 
 | 96 | +  @override  | 
 | 97 | +  void addListener(void Function() listener) {  | 
 | 98 | +    for (final child in _children) {  | 
 | 99 | +      child?.addListener(listener);  | 
 | 100 | +    }  | 
 | 101 | +  }  | 
 | 102 | + | 
 | 103 | +  @override  | 
 | 104 | +  void removeListener(void Function() listener) {  | 
 | 105 | +    for (final child in _children) {  | 
 | 106 | +      child?.removeListener(listener);  | 
 | 107 | +    }  | 
 | 108 | +  }  | 
 | 109 | + | 
 | 110 | +  @override  | 
 | 111 | +  String toString() {  | 
 | 112 | +    return 'Listenable.merge([${_children.join(", ")}])';  | 
 | 113 | +  }  | 
 | 114 | +}  | 
0 commit comments