simple_builder.dart
3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import 'dart:async';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'list_notifier.dart';
typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot);
typedef ValueBuilderBuilder<T> = Widget Function(
T snapshot, ValueBuilderUpdateCallback<T> updater);
/// Manages a local state like ObxValue, but uses a callback instead of
/// a Rx value.
///
/// Example:
/// ```
/// ValueBuilder<bool>(
/// initialValue: false,
/// builder: (value, update) => Switch(
/// value: value,
/// onChanged: (flag) {
/// update( flag );
/// },),
/// onUpdate: (value) => print("Value updated: $value"),
/// ),
/// ```
class ValueBuilder<T> extends StatefulWidget {
final T initialValue;
final ValueBuilderBuilder<T> builder;
final void Function()? onDispose;
final void Function(T)? onUpdate;
const ValueBuilder({
Key? key,
required this.initialValue,
this.onDispose,
this.onUpdate,
required this.builder,
}) : super(key: key);
@override
_ValueBuilderState<T> createState() => _ValueBuilderState<T>(initialValue);
}
class _ValueBuilderState<T> extends State<ValueBuilder<T>> {
T value;
_ValueBuilderState(this.value);
@override
Widget build(BuildContext context) => widget.builder(value, updater);
void updater(T newValue) {
if (widget.onUpdate != null) {
widget.onUpdate!(newValue);
}
setState(() {
value = newValue;
});
}
@override
void dispose() {
super.dispose();
widget.onDispose?.call();
if (value is ChangeNotifier) {
(value as ChangeNotifier?)?.dispose();
} else if (value is StreamController) {
(value as StreamController?)?.close();
}
}
}
class ObxElement = StatelessElement with ObserverComponent;
// It's a experimental feature
class Observer extends ObxStatelessWidget {
final WidgetBuilder builder;
const Observer({Key? key, required this.builder}) : super(key: key);
@override
Widget build(BuildContext context) => builder(context);
}
/// A StatelessWidget than can listen reactive changes.
abstract class ObxStatelessWidget extends StatelessWidget {
/// Initializes [key] for subclasses.
const ObxStatelessWidget({Key? key}) : super(key: key);
@override
StatelessElement createElement() => ObxElement(this);
}
/// a Component that can track changes in a reactive variable
mixin ObserverComponent on ComponentElement {
List<Disposer>? disposers = <Disposer>[];
void getUpdate() {
if (disposers != null) {
_safeRebuild();
}
}
Future<bool> _safeRebuild() async {
if (dirty) return false;
if (SchedulerBinding.instance == null) {
markNeedsBuild();
} else {
// refresh was called during the building
if (SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.idle) {
// Await for the end of build
await SchedulerBinding.instance!.endOfFrame;
if (dirty) return false;
}
markNeedsBuild();
}
return true;
}
@override
Widget build() {
return Notifier.instance.append(
NotifyData(disposers: disposers!, updater: getUpdate), super.build);
}
@override
void unmount() {
super.unmount();
for (final disposer in disposers!) {
disposer();
}
disposers!.clear();
disposers = null;
}
}