Search code examples
asynchronousdartflutterrxdart

Stream.last callback never firing


I'm writing my Flutter app with a BLoC pattern. And what I want is pretty simple: show a TextField with the last value from a stream as an initial value.

There is the simple bloc:

class MyBloc {
  BehaviorSubject<String> _titleController;
  Stream<String> get outTitle => _titleController.stream;
  Sink<String> get inTitle => _titleController.sink;

  MyBloc(Model model) {
    _titleController = BehaviorSubject(seedValue: model.title); 
  }
}

And the view with a FutureBuilder:

@override
Widget build(BuildContext context) {
  var bloc = /* get the bloc from a widgets' hierarchy */
  return FutureBuilder(
    future: bloc.outTitle.last,
    builder: (context, snapshot) {
      return TextField(
        controller: TextEditingController.fromValue(
          TextEditingValue(text: snapshot.data ?? 'null')
        ),
      );
    }
  );
}

The problem is that the FutureBuilder calls the builder only once with null data and "waiting" connection state.

What I tried:

  1. Replace FutureBuilder with StreamBuilder and outTitle.last with outTitle.last.asStream();
  2. Call outTitle.last.then() outside widgets and from bloc constructor;
  3. Change signature of outTitle to ValueObservable and call last.wrapped;
  4. Change Rx's BehaviorSubject to vanilla StreamController;
  5. Add to stream some values before building the view;

Nothing happens. Just streams with StreamBuilders work well, but it is impossible to get the last value from last property.

Where can the problem lie?


Solution

  • last is only emitted when the stream is closed. Otherwise the stream can't know what the last event is.

    When you call

    _titleController.close()
    

    last will emit a value.