Не существует чистого способа прослушивания StatelessWidget для прослушивания / потока.Вам всегда понадобится StatefulWidget.
С другой стороны, вы можете использовать композицию для написания этого StatefulWidget только один раз и покончить с этим.
Типичные примеры дляэтим шаблоном являются виджеты, такие как ValueListenableBuilder
, StreamBuilder
или AnimatedBuilder
.Но можно сделать то же самое и для прослушивания.
Вы бы использовали это так:
class Foo extends StatelessWidget {
Foo({Key key, this.counter}): super(key: key);
final ValueListenable<int> counter;
@override
Widget build(BuildContext context) {
return ValueListenableListener(
valueListenable: counter,
onChange: (value) {
// TODO: do something
},
child: Something(),
);
}
}
Где ValueListenableListener
реализован следующим образом:
class ValueListenableListener<T> extends StatefulWidget {
const ValueListenableListener(
{Key key, this.valueListenable, this.onChange, this.child})
: super(key: key);
final ValueListenable<T> valueListenable;
final ValueChanged<T> onChange;
final Widget child;
@override
_ValueListenableListenerState createState() =>
_ValueListenableListenerState();
}
class _ValueListenableListenerState extends State<ValueListenableListener> {
@override
void initState() {
super.initState();
widget.valueListenable?.addListener(_listener);
_listener();
}
@override
void didUpdateWidget(ValueListenableListener oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.valueListenable != widget.valueListenable) {
oldWidget.valueListenable?.removeListener(_listener);
widget.valueListenable?.addListener(_listener);
_listener();
}
}
@override
void dispose() {
widget.valueListenable?.removeListener(_listener);
super.dispose();
}
void _listener() {
widget.onChange?.call(widget.valueListenable.value);
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}