flowr_dart 4.0.1
flowr_dart: ^4.0.1 copied to clipboard
Base FlowR library for pure Dart
FlowR Dart #
State management based on Reactive programming for pure Dart.
Install #
dart pub add flowr_dart
Tip
If you are using Flutter, it is highly recommended to use the flowr package, which provides MVVM support and Flutter-specific features.
Getting started #
import 'package:flowr_dart/flowr_dart.dart';
class Counter extends FlowR<int> {
Counter({required int initialState}) : super(initialState);
incrementCounter() => update((old) {
logger('incrementCounter: $old');
return old + 1;
});
incrementSlowly() => update(
(old) async {
await Future<void>.delayed(const Duration(milliseconds: 300));
return old + 1;
},
mutexTag: 'counter',
);
}
Future<void> main() async {
Logger.root.level = Level.INFO;
Logger.root.onRecord.listen(LoggableMx.devLogRecordPrinter);
final counter = Counter(initialState: 0);
await counter.incrementCounter();
print('counter: ${counter.value}');
counter.dispose();
}
Core APIs #
FlowB<E, S>is the bloc-native event-driven base class and extendsBloc<E, S>.FlowR<T>is the method-driven base class and extendsCubit<T>.FlowR<T>.streamuses Cubit's nativeStream<T>semantics and does not replay the current state to new subscribers.updatereads the current value, runs an updater, catches failures, and callsputon success.runCatchingis available for non-state work that should share the same error and skip handling.skpIfandskpNullthrowSkipError, which stops the current flow without treating it as a failure.autoDispose(subscription)cancels registered stream subscriptions whendisposeis called.
FlowR follows bloc equality semantics: if value == currentValue, listeners are not notified. Prefer immutable state updates, for example update((old) => old.copyWith(...)).
Concurrency #
update and runCatching can be scheduled with:
debounceTag: wait until calls stop, then run the last call.throttleTag: run at most once during the configured window.mutexTag: run immediately and ignore overlapping calls with the same tag.slowlyMs: window size in milliseconds for debounce and throttle.
Tags are scoped to the FlowR instance. Use stable tag values for each independent action.
Stream helpers #
final names = counter.stream.distinctWith((count) => 'count: $count');
final evenValues = counter.stream.where((count) => count.isEven);
distinctByfilters events by the selected key.distinctWithmaps then de-duplicates mapped values.distinctUniquefilters duplicates across the whole stream history.
Logging #
FlowR uses package:logging. Configure the root logger once in your app:
Logger.root.level = Level.INFO;
Logger.root.onRecord.listen(LoggableMx.devLogRecordPrinter);
Set Logger.root.level = Level.FINE to see normal put, debounce, throttle, mutex, and SkipError logs.
Disposal #
Call dispose when a FlowR instance is no longer used. This closes the state subject, cancels subscriptions registered through autoDispose, and disposes pending debounce, throttle, or mutex timers.
Run example #
Demo FlowR: for dart main.dart
# From workspace root
dart run examples/example/lib/main.dart