Line data Source code
1 : // ignore_for_file: hash_and_equals 2 : 3 : import 'dart:async'; 4 : 5 : import 'package:meta/meta.dart'; 6 : 7 : typedef ListenerCallback<T> = void Function(T); 8 : 9 : /// Define a base notifier for SimpleNotifier and StateNotifier 10 : abstract class BaseNotifier<S> { 11 : /// used to check if a notifier was disposed 12 : bool _disposed = false; 13 : 14 : /// Tell us if the notifier was disposed 15 12 : bool get disposed => _disposed; 16 : 17 : /// Tell us if the notifier is mounted 18 2 : bool get mounted => !_disposed; 19 : 20 4 : @mustCallSuper 21 : FutureOr<void> dispose() { 22 4 : _disposed = true; 23 : } 24 : 25 : // Custom implementation of hash code optimized for reading notifiers. 26 4 : @override 27 4 : int get hashCode => _cachedHash; 28 : final int _cachedHash = _nextHashCode = (_nextHashCode + 1) % 0xffffff; 29 : static int _nextHashCode = 1; 30 : } 31 : 32 : mixin ListeneableNotifier<T> { 33 : final _listeners = <ListenerCallback<T>>[]; 34 : 35 : /// completer to check if we are emiting events before call dispose 36 : Completer<void>? _isBusy; 37 : 38 : /// returns true when the current notifier has subscribers 39 12 : bool get hasListeners => _listeners.isNotEmpty; 40 : 41 : void Function()? _disposableCallback; 42 : 43 6 : void _complete() { 44 18 : if (_isBusy != null && !_isBusy!.isCompleted) { 45 12 : _isBusy!.complete(); 46 : } 47 : } 48 : 49 : /// notify to listeners and rebuild the widgets 50 : /// 51 : /// only SimpleNotifier or StateNotifier are allowed to call this method, DON'T call to this method since 52 : /// a sub-type of SimpleNotifier or StateNotifier 53 6 : void notifyListeners(T data) { 54 12 : _isBusy = Completer(); 55 12 : if (_listeners.isNotEmpty) { 56 8 : for (final entry in _listeners) { 57 4 : entry(data); 58 : } 59 : } 60 6 : _complete(); 61 : } 62 : 63 : /// add a new listener 64 4 : void addListener(ListenerCallback<T> listener) { 65 8 : _listeners.add(listener); 66 : } 67 : 68 : /// remove a listener from the notifier 69 4 : void removeListener(ListenerCallback<T> listener) { 70 8 : if (_listeners.isNotEmpty) { 71 8 : _listeners.remove(listener); 72 : 73 4 : if (!hasListeners) { 74 7 : _disposableCallback?.call(); 75 : } 76 : } 77 : } 78 : 79 4 : @protected 80 : Future<void> clearListeners() async { 81 8 : await _isBusy?.future; 82 8 : _listeners.clear(); 83 : } 84 : 85 3 : @protected 86 : void setDisposableCallback(void Function() disposableCallback) { 87 3 : _disposableCallback = disposableCallback; 88 : } 89 : }