Skip to content

Commit

Permalink
refactor: RemoteParameter class to improve listener
Browse files Browse the repository at this point in the history
management
  • Loading branch information
naipaka committed Nov 6, 2023
1 parent 272dd00 commit e5b6ca6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import 'dart:async';

/// A class that holds the value of a parameter fetched from a remote.
/// It also provides a Stream of updated parameter information.
class RemoteParameter<T> {
RemoteParameter({
required T value,
required Stream<void> onConfigUpdated,
required this.onConfigUpdated,
required this.activateAndRefetch,
}) : _value = value {
onConfigUpdated.listen((_) async {
_value = await activateAndRefetch();
_notifyListeners();
});
}
}) : _value = value;

/// A Stream of updated parameter information.
Stream<void> onConfigUpdated;

/// A function that will activate the fetched config and refetch the value.
/// This is useful for when you want to force a refetch of the value.
Expand All @@ -22,10 +22,32 @@ class RemoteParameter<T> {

final List<void Function(T value)> _listeners = [];

late StreamSubscription<void> _subscription;

/// Add a listener to be notified when the value changes.
/// Executed when the remote value is updated.
void addListener(void Function(T value) listener) {
_listeners.add(listener);

if (_listeners.length == 1) {
// When the listener is added for the first time,
// monitor the onConfigUpdated stream.
_subscription = onConfigUpdated.listen((_) async {
_value = await activateAndRefetch();
_notifyListeners();
});
}
}

/// Remove a listener.
Future<void> removeListener(void Function(T value) listener) async {
_listeners.remove(listener);

if (_listeners.isEmpty) {
// When the last listener is removed,
// cancel the subscription to the onConfigUpdated stream.
await _subscription.cancel();
}
}

void _notifyListeners() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,31 @@ void main() {
expect(rp.value, 20);
});

test('should not call listener when removed', () async {
final controller = StreamController<void>();
addTearDown(controller.close);

final rp = RemoteParameter<int>(
value: 10,
onConfigUpdated: controller.stream,
activateAndRefetch: () async => 20,
);

var updatedValue = 10;
void listener(int value) {
updatedValue = value;
}

rp.addListener(listener);

await rp.removeListener(listener);
controller.add(null);
await Future<void>.delayed(Duration.zero);

expect(rp.value, 10);
expect(updatedValue, 10);
});

test('should refetch value when config updates', () async {
final controller = StreamController<void>();
addTearDown(controller.close);
Expand All @@ -50,7 +75,7 @@ void main() {
refetchCalled = true;
return 20;
},
);
)..addListener((_) {});

controller.add(null);

Expand Down

0 comments on commit e5b6ca6

Please sign in to comment.