Skip to content

Instantly share code, notes, and snippets.

@2qp
Forked from theniceboy/state.dart
Created October 10, 2022 18:21
Show Gist options
  • Save 2qp/53c40cdbcc855aa3e6d54bc2ebe990d4 to your computer and use it in GitHub Desktop.
Save 2qp/53c40cdbcc855aa3e6d54bc2ebe990d4 to your computer and use it in GitHub Desktop.
Simple stream-based state management in Flutter/Dart
import 'dart:async';
import 'package:async/async.dart';
import 'package:flutter/widgets.dart';
/*
This class is a little bit different than the [ValueNotifier] class:
- Setting the value ALWAYS notifies listeners, even if the value is the same.
- It uses streams over [ValueListenableBuilder]'s setState approach to make it
easier to use with other async code.
*/
class Observable<T> {
T _value;
T get value => _value;
set value(T v) {
_value = v;
_controller.add(v);
}
void notify() {
_controller.add(_value);
}
void setIfChanged(T v) {
if (v != _value) {
value = v;
}
}
Observable(this._value);
final _controller = StreamController<T>.broadcast();
Stream<T> get stream => _controller.stream;
}
class Observer<T> extends StatelessWidget {
final Observable<T> observable;
final Widget Function(BuildContext, T) builder;
const Observer({required this.observable, required this.builder, Key? key}) : super(key: key);
@override
Widget build(context) {
return StreamBuilder<T>(
stream: observable.stream,
builder: (context, value) {
return builder(context, observable.value);
},
);
}
}
class MultiObserver extends StatelessWidget {
final List<Observable> observables;
final Widget Function(BuildContext, List) builder;
const MultiObserver({required this.observables, required this.builder, Key? key})
: super(key: key);
@override
Widget build(context) {
return StreamBuilder(
stream: StreamGroup.merge(observables.map((o) => o.stream)),
builder: (context, value) {
return builder(context, observables.map((o) => o.value).toList());
},
);
}
}
/// A simplified [Observable] with "no" values
class Notifier extends Observable<bool> {
Notifier() : super(true);
}
class NotifierBuilder extends StatelessWidget {
final Notifier notifier;
final Widget Function(BuildContext) builder;
const NotifierBuilder({required this.notifier, required this.builder, Key? key})
: super(key: key);
@override
Widget build(context) {
return StreamBuilder(
stream: notifier.stream,
builder: (context, _) {
return builder(context);
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment