StreamBuilder从流仅接收最后一个项目(StreamBuilder receives on

2019-10-16 12:16发布

我ApplicationBloc是widget树的根。 在欧盟的构造,我听从包含JSON解码模型存储库中的数据流,并将其转发到由StreamBuilder听了另一个流。

我预计,StreamBuilder将收到车型逐一并将它们添加到AnimatedList。 但问题在于:StreamBuilder的建设者火灾只流中的最后一个项目一次。

例如,一些模型躺在ID分别为0,1,2和3。所有这些本地存储库中,从发射,所有的这些都成功地把在流控制器,但只有最后一个模型(id为== 3 )出现在AnimatedList。

库:

class Repository {
  static Stream<Model> load() async* {
    //...
    for (var model in models) {
      yield Model.fromJson(model);
    }
  }
}

集团:

class ApplicationBloc {
  ReplaySubject<Model> _outModelsController = ReplaySubject<Model>();
  Stream<Model> get outModels => _outModelsController.stream;

  ApplicationBloc() {
    TimersRepository.load().listen((model) => _outModelsController.add(model));
  }
}

main.dart:

void main() {
  runApp(
    BlocProvider<ApplicationBloc>(
      bloc: ApplicationBloc(),
      child: MyApp(),
    ),
  );
}

//...

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    final ApplicationBloc appBloc = //...

    return MaterialApp(
      //...
      body: StreamBuilder(
        stream: appBloc.outModels,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            var model = snapshot.data;
            /* inserting model to the AnimatedList */
          }

          return AnimatedList(/* ... */);
        },
      ),
    );
  }
}

有趣的通知:在StreamBuilder的_subscribe()方法昂达()回调触发所需的次数,但建()方法触发一次。

Answer 1:

你需要一个Stream输出一个List<Model ,而不是一个单一的元素。 此外,听流将其添加到另一个ReplaySubject将由2(!!!)帧延迟输出流,所以这将是最好有一个单链。

class TimersRepository {
  // maybe use a Future if you only perform a single http request!
  static Stream<List<Model>> load() async* {
    //...
    yield models.map((json) => Model.fromJson(json)).toList();
  }
}

class ApplicationBloc {
  Stream<List<Model>> get outModels => _outModels;
  ValueConnectableObservable<List<Model>> _outModels;
  StreamSubscription _outModelsSubscription;

  ApplicationBloc() {
    // publishValue is similar to a BehaviorSubject, it always provides the latest value,
    // but without the extra delay of listening and adding to another subject
    _outModels = Observable(TimersRepository.load()).publishValue();

    // do no reload until the BLoC is disposed
    _outModelsSubscription = _outModels.connect();
  }

  void dispose() {
    // unsubcribe repo stream on dispose
    _outModelsSubscription.cancel();
  }
}

class _MyAppState extends State<MyApp> {
  ApplicationBloc _bloc;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<Model>>(
      stream: _bloc.outModels,
      builder: (context, snapshot) {
        final models = snapshot.data ?? <Model>[];
        return ListView.builder(
          itemCount: models.length,
          itemBuilder: (context, index) => Item(model: models[index]),
        );
      },
    );
  }
}


文章来源: StreamBuilder receives only last item from stream