3

My StreamBuilder in view:

Widget build(BuildContext context) {
    print("rebuilding..."); // as of now this gets called only on view initialization and never again - i.e. not on new events going through alarmController.stream

    return StreamBuilder(
        stream: widget.bloc.alarmController.stream,
        initialData: Alarm(''),
        builder: (BuildContext context, AsyncSnapshot<Alarm> snapshot) {
          if (!snapshot.hasData) {
            return Center(
              child: Text(StringLiterals.NO_ALARM_DATA_MSG))
            );
          }

          return Switch(
                  activeColor: Colors.red,
                  value: snapshot.data.status == 'Started',
                  onChanged: (bool _value) {
                    _newAlarmValue = _value;
                    _askAlarmConfirmation();
                  }));
        });
  }

meat of my bloc:

AlarmBloc(this.Api) {
    getAlarm();
}
  getAlarm() async {
    Alarm response = await Api.getAlarmStatus();
    alarmController.sink.add(response); // here im adding new event, therefore streambuilder should rebuild, right?
}

And lastly the code I call to initiate new event(in this case it's firebase message):

if(_message.notification.body.contains("Alarm") && IS_LOGGED_IN == true) {
   alarmBloc.getAlarm();
 }

So the problem is StreamBuilder not rebuilding whenever new event passes through alarmController.stream. What could be the reason?

Alan Kałuża
  • 515
  • 5
  • 19

2 Answers2

2

Your bloc needs to be a type of Stream. The same stream type as your StreamBuilder. For example your bloc needs to be a Stream<Alarm>. Otherwise stream: widget.bloc.alarmController.stream, will only be called once and won't act as an asynchronous stream of data.

Your Streambuilder needs to check for connection states

Widget build(BuildContext context) {
    print("rebuilding..."); // as of now this gets called only on view initialization and never again - i.e. not on new events going through alarmController.stream

    return StreamBuilder<Alarm>(
        stream: widget.bloc.alarmController.stream,
        initialData: Alarm(''),
        builder: (BuildContext context, AsyncSnapshot<Alarm> snapshot) {
          if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
      switch (snapshot.connectionState) {
        case ConnectionState.waiting:
          return Text('Loading...'); 
        default: 
          if (!snapshot.hasData) {
             return Center(
                child: Text(StringLiterals.NO_ALARM_DATA_MSG))
             );
          }

         return Switch(
              activeColor: Colors.red,
              value: snapshot.data.status == 'Started',
              onChanged: (bool _value) {
                _newAlarmValue = _value;
                _askAlarmConfirmation();
              }));
      }

Here are the other types of connection states you can check for:

async.dart

    enum ConnectionState {
  /// Not currently connected to any asynchronous computation.
  ///
  /// For example, a [FutureBuilder] whose [FutureBuilder.future] is null.
  none,

  /// Connected to an asynchronous computation and awaiting interaction.
  waiting,

  /// Connected to an active asynchronous computation.
  ///
  /// For example, a [Stream] that has returned at least one value, but is not
  /// yet done.
  active,

  /// Connected to a terminated asynchronous computation.
  done,
}
Val
  • 1,260
  • 5
  • 23
  • 39
  • Unfortunately, this isn't the case. The connection is not being terminated and even with StreamBuilder type given it's still not rebuilding the widget on new event being added to sink... – Alan Kałuża May 24 '19 at 07:53
  • Streams can be tricky. There are more options we can check out for you. We would need to reconfigure the calling stream in place of sending the 'response' back through the controller. It looks like the getAlarm is only getting call on the build and isn't streaming data back asynchronously. First can you tell me what type of response Type you are expecting from getAlarm? – Val May 24 '19 at 14:50
1

The issue was I was instantiaing my BLOC incorrectly(second one) and working on a second parallel stream and therefore not the one passed to StreamBuilder.

Alan Kałuża
  • 515
  • 5
  • 19