|
| 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