gpt4 book ai didi

flutter - StreamBuilder 仅接收流中的最后一项

转载 作者:IT王子 更新时间:2023-10-29 06:59:12 28 4
gpt4 key购买 nike

我的 ApplicationBloc 是小部件树的根。在 bloc 的构造函数中,我正在收听来自存储库的流,其中包含从 JSON 解码的模型并将它们转发到另一个流,该流由 StreamBuilder 收听。

我预计 StreamBuilder 会一个接一个地接收模型并将它们添加到 AnimatedList 中。但是有一个问题:StreamBuilder 的构建器只在流中的最后一个项目触发一次。

例如,几个模型位于本地存储中,id 为 0、1、2 和 3。所有这些都是从存储库发出的,所有这些都成功放入流 Controller ,但只有最后一个模型(id == 3) 出现在动画列表中。

存储库:

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

Bloc :

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

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

主飞镖:

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() 方法中,onData() 回调触发所需次数,但 build() 方法仅触发一次。

最佳答案

你需要一个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]),
);
},
);
}
}

关于flutter - StreamBuilder 仅接收流中的最后一项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53903650/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com