Introduction¶
Adapted from internal documentation by Bridgecat
Welcome to dust
. Please checkout the Quick Start Guide.
As you would probably know by now, dust
handles three things at once:
- State Management;
- Persistence;
- Synchronization (to be implemented).
We want to do this so that when we build new apps, we don't need to define our models multiple times using multiple libraries while keeping everything 1-1 mapped. Our earlier experience with such attempts were horrible, and it significantly hindered our development of the file management page and the preferences page.
Previously, we used:
The design of Qinhuai draws inspiration from MobX, Riverpod, Isar, as well as Freezed.
Reactive States¶
Note that this portion is rather a big-picture view of the reactivity of dust. For simplicity of use, many classes introduced here would be automatically generated by
dust_generator
. Reading through this part here would not likely be very applicable unless encountered with more advanced usecases. However, it would hopefully make you understand more about howdust
works as a state management solution.
Ideally, when any value shown by a UI widget is changed, the widget should be
rebuilt to reflect the latest state. In Qinhuai there are two closely-related
interfaces: Observable<T>
and Observer
.
Observable<T>
¶
Observable<T>
: provides a get(Observer? o)
function which retrieves its
value and (optionally) registers an "observer" o
.
- The "observer" will be "notified" when there is a possible change to the underlying value.
- For clarity, prefer calling the aliases
watch(Observer o)
orpeek()
.
Concrete classes can implement Observable<T>
. Here are a list of common
implementations:
Active<T>
: the simplest obserable thing. Its value can be changed using theset(T value)
method. Data stored inActive<T>
will be transient values, and they will not be persisted to local storage. This is ideal for temporary reactive values.Atom<T>
,Link<T>
,BackLinks<T>
: these are observables that store data that can and will automatically be persisted to the disk and synchronized.Reactive<T>
: computes its value from otherObservable<T>
s and caches it. When any of its dependencies is "notified", it will be "notified" as well. The value would be recomputed lazily, ad the next invocation ofget
.
Observer
¶
Observer
: provides a visit(List<VoidCallback> posts)
function which
allows it to be "notified".
- It can choose to execute side effects inside the
visit
function, or (optionally) push "post-visit callbacks" into theposts
list, having them executed after the graph traversal completes. - This
visit
is for implementation only. prefer callingnotify()
.
Concrete classes can implement Observer
:
Trigger<T>
: watches anObservable<T>
and triggers a callback each time it is notified.- Sometimes, the watched value may be notified without actually changing (e.g.
when something is assigned the same value multiple times). The variant
Comparer<T>
would provide the previous value to thecallback
, allowing filtering of such events.
Widgets¶
There are two Flutter widgets that operate with the state management portion
of dust
:
ReactiveWidget
: a widget that provides a "observer" o
for use inside its
builder
parameter.
- The widget will be flagged for rebuild when the "observer" is "notified".
- Usage: inherit and override the
build
method.
ReactiveBuilder
: a widget that provides a "observer" o
for use inside its
builder
parameter.
- The widget will be flagged for rebuild when the "observer" is "notified".
- Usage: place it anywhere in a widget tree.
API Comparisons¶
The API of dust
closely mimics that of Riverpod
:
Data Node | Widget Node | Data B - Data A | Widget B - Data A | Update Data A | Force Update Widget A | |
---|---|---|---|---|---|---|
ChangeNotifier (built-in) |
ValueNotifier (immutable)ChangeNotifier (mutable, manual) |
AnimatedWidget (base)AnimatedBuilder (builder) |
A.addListener(() { /* Update B from A */ }) |
Include A in B's listenable /animation property (cannot be changed onece B is created) |
A.value = value (immutable) A.notifyListeners() (mutable, manual) |
(no special way to force update widgets) |