Last active
October 19, 2023 16:07
-
-
Save danielgomezrico/361e862af6a2f3c78141bee9ec546044 to your computer and use it in GitHub Desktop.
Dart/Flutter - Extensions to emit ChangeNotifier changes as a Stream, very useful for unit testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Function to get the changed value everytime | |
typedef GetChangeFunction<T> = T Function(); | |
extension AsStream<T> on ChangeNotifier { | |
Stream<T> statusAsStream(GetChangeFunction<T> getChange) { | |
final controller = StreamController<T>(); | |
// Redirect status changes into the Stream | |
final notify = () => controller.add(getChange()); | |
addListener(notify); | |
controller.onCancel = () => removeListener(notify); | |
// As this is intended for tests it should close if no emitions were done | |
// in x period of time to avoid a never ending test | |
Future.delayed(Duration(seconds: 5)).then((value) => controller.close()); | |
return controller.stream; | |
} | |
StreamController<T> statusAsStreamController(GetChangeFunction<T> getChange) { | |
final controller = StreamController<T>(); | |
// Redirect status changes into the Stream | |
final notify = () => controller.add(getChange()); | |
addListener(notify); | |
controller.onCancel = () => removeListener(notify); | |
return controller; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Your ViewModel abstraction | |
abstract class ViewModel<S> with ChangeNotifier { | |
S _status; | |
S get status => _status; | |
set status(S value) { | |
_status = value; | |
notifyListeners(); | |
} | |
} | |
// Cleaner extensions | |
extension AsStream<T> on ViewModel<T> { | |
Stream<T> statusStream() { | |
final controller = StreamController<T>(); | |
// Redirect status changes into the Stream | |
final notify = () => controller.add(status); | |
addListener(notify); | |
controller.onCancel = () => removeListener(notify); | |
// Timeout to cancel the stream if no changes | |
Future.delayed(Duration(seconds: 5)).then((value) => controller.close()); | |
return controller.stream; | |
} | |
StreamController<T> statusStreamController() { | |
final controller = StreamController<T>(); | |
// Redirect status changes into the Stream | |
final notify = () => controller.add(status); | |
addListener(notify); | |
controller.onCancel = () => removeListener(notify); | |
return controller; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment