I would like to create a StatefulWidget which I'll use all over the app for listening streams of different types. Since I try to keep all the widgets Stateless I wanted to extract this functionality.
I've created this:
class StreamListener<T> extends StatefulWidget {
const StreamListener({
Key? key,
required this.stream,
required this.onNewData,
required this.child,
}) : super(key: key);
final Stream<T?> stream;
final void Function(T data) onNewData;
final Widget child;
@override
State<StreamListener> createState() => _StreamListenerState<T>();
}
class _StreamListenerState<T> extends State<StreamListener> {
late StreamSubscription<T?> streamSubscription;
@override
void initState() {
streamSubscription = (widget.stream as Stream<T?>).listen(
(T? data) {
if (data != null) {
widget.onNewData(data);
}
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
@override
void dispose() {
streamSubscription.cancel();
super.dispose();
}
}
Then somewhere in the Widgets tree I use:
return StreamListener<int>(
stream: context.read<MyCubit>().toastStream,
onNewData: (int data) {
print("Received: $data");
},
child: SomeStatelessWidget(),
}
Stream logic is added to the Cubit like that:
mixin ToastStreamForCubit<T> {
final StreamController<T> _toastStreamController = StreamController<T>();
get toastStream => _toastStreamController.stream;
void emitToastEvent(T event) {
_toastStreamController.add(event);
}
}
And when I call let's say emitToastEvent(1)
.
I receive type '(int) => void' is not a subtype of type '(dynamic) => void'
.
on line widget.onNewData(data);
.
I'm not sure what is going on. I thought I've mapped all the functions and classes to a particular generic type (T), but it still says something about dynamic
.
CodePudding user response:
You are missing T
while extending State<StreamListener>
. It should be
class _StreamListenerState<T> extends State<StreamListener<T>>