调用 StreamController.sink.add 时 StreamBuilder 没有反应
Posted
技术标签:
【中文标题】调用 StreamController.sink.add 时 StreamBuilder 没有反应【英文标题】:StreamBuilder is not reacting when calling StreamController.sink.add 【发布时间】:2019-08-18 00:31:31 【问题描述】:我的 Flutter 应用中有一个专门用于编辑对象列表的屏幕。当您按下编辑按钮时,会弹出一个模式,允许您编辑对象值。当您关闭模型时,列表会通过 BLoC 刷新。但是,当调用刷新列表的方法时,什么也没有发生。
bloc.dart
class Bloc
final _provider = ModelProvider();
final _controller = StreamController<List<Model>>();
Stream<List<Model>> get models => _controller.stream;
void getModels() async
final List<Model> models = await _provider.readAll();
_controller.sink.add(models);
Future<int> saveModel(Model model) async
final int id = await _provider.write(model);
return id;
list_screen.dart
class ListScreen extends StatelessWidget
final bloc = Bloc();
@override
Widget build(BuildContext context)
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
// SliverAppBar ...
StreamBuilder<List<Model>>(
stream: bloc.models,
builder: (context, snapshot)
if (snapshot.hasData)
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) =>
ListTile(
title: Text(snapshot.data[index].name),
onPressed: () => _editModel(context),
),
),
else
bloc.getModels();
return Container();
),
],
),
);
void _editModel(BuildContext context) async
final Model edited = await showDialog(
context: context,
builder: (context) => EditModal(),
);
if (edited != null)
await bloc.saveModel(edited);
bloc.getModels();
我知道数据已正确存储在数据库中,因为如果我转到上一个屏幕然后返回到编辑屏幕,数据就会更新。谁能帮我弄清楚为什么StreamBuilder
没有重建?
【问题讨论】:
您解决了吗?我刚刚进入 Flutter 开发并遇到了这个确切的问题。 我从未解决过这个问题。我切换到 Provider 进行状态管理,但这对我来说很容易,因为我处于开发的早期阶段。 【参考方案1】:也许问题是你在保存后调用 bloc.getModels 时没有放置等待,或者保存方法给出错误并破坏不运行 getModels 的方法
【讨论】:
将await
与Bloc.getModels
一起使用将不起作用,因为它不会返回Future
,而且我知道数据存储正确,因为我可以在@987654325 中打印models
@ 并看到它获取更新的数据。【参考方案2】:
希望这会对某人有所帮助:对我来说,问题在于,当我更新列表时,它实际上是存储在字段中的相同引用。每次创建一个新列表并且不将列表存储在同一字段中解决了它。我们无法从问题中看到您的 ModelProvider 内部,但看起来可能是同一个问题。
第一次之后没有更新:
class MiniaturePaintsBloc implements Bloc
List<MiniaturePaint> _miniaturePaints;
final _controller = StreamController<List<MiniaturePaint>>.broadcast();
Stream<List<MiniaturePaint>> get miniaturePaintsStream => _controller.stream;
void fetchMiniaturePaints() async
QuerySnapshot querySnapshot =
await Firestore.instance.collection("MiniaturePaints").getDocuments(source: Source.serverAndCache);
_miniaturePaints = querySnapshot.documents.map((doc) => _docToMiniaturePaint(doc)).toList();
_controller.sink.add(_miniaturePaints);
//rest of BloC code here
通过删除该字段,它现在会更新 StreamBuilder:
class MiniaturePaintsBloc implements Bloc
final _controller = StreamController<List<MiniaturePaint>>.broadcast();
Stream<List<MiniaturePaint>> get miniaturePaintsStream => _controller.stream;
void fetchMiniaturePaints() async
QuerySnapshot querySnapshot =
await Firestore.instance.collection("MiniaturePaints").getDocuments(source: Source.serverAndCache);
List<MiniaturePaint> miniaturePaints = querySnapshot.documents.map((doc) => _docToMiniaturePaint(doc)).toList();
_controller.sink.add(miniaturePaints);
//rest of BLoC code here
【讨论】:
这在技术上是完全一样的。没有什么区别。您正在将 _miniaturePaints 列表更改为两个代码 sn-ps 中的不同列表。一个是字段这一事实没有任何区别,因为它是我们想要的数据,而不是它是字段还是变量。以上是关于调用 StreamController.sink.add 时 StreamBuilder 没有反应的主要内容,如果未能解决你的问题,请参考以下文章