Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Generic Widget for listening Streams in Flutter

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

You are missing T while extending State<StreamListener>. It should be

class _StreamListenerState<T> extends State<StreamListener<T>>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading