使用changeNotifier更新streambuilder dynammanmanmy

发布于 2025-02-07 19:11:37 字数 1996 浏览 2 评论 0原文

我有以下状态窗口小部件的构建方法。我正在尝试使用changeNotifier动态地测试更新Firebase Collection流。代码如下:

@override
  Widget build(BuildContext context) {
    final List<String> types = ["pop", "ballad", ''];
    final SongStreamNotifier songStreamNotifier =
        Provider.of<SongStreamNotifier>(context);
    developer.log("Rebuilding Scaffold");
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          types.shuffle();
          final songType = types.first;
          songStreamNotifier.getSongsStream(songType);
        },
      ),
      body: StreamBuilder<QuerySnapshot>(
          stream: songStreamNotifier.songs,
          builder: (context, snapshot) {
            developer.log("Rebuilding stream");
            if (snapshot.hasError) {
              return Text(snapshot.error.toString());
            } else if (snapshot.hasData) {
              return ListView.builder(
                  itemCount: snapshot.data!.size,
                  itemBuilder: (BuildContext ctx, int index) {
                    return Text(snapshot.data!.docs[index].get('name'));
                  });
            } else {
              return Container();
            }
          }),
    );
  }

通知符正确调用,我可以看到有关构建方式的所有日志消息,但值不会更改。 ChangeNotifier的代码如下:

class SongStreamNotifier extends ChangeNotifier {
  Stream<QuerySnapshot> stream = Stream.empty();
  final SongService songService = SongService();

  Stream<QuerySnapshot> get songs {
    return stream;
  }

  getSongsStream(String type) {
    developer.log('type: $type');
    stream = songService.getSongs(type);
    notifyListeners();
  }
}

非常直截了当:Sonsevice.getsongs根据Songtype过滤歌曲。 我仍然不明白提供商如何更新小部件状态。我怎么会看到构建器方法开始运行,而流式构造者总是可以获取相同的值?

I have the following build method of a statefull widget. I am trying to test updating a Firebase collection stream dynamically using a ChangeNotifier. The code is the following:

@override
  Widget build(BuildContext context) {
    final List<String> types = ["pop", "ballad", ''];
    final SongStreamNotifier songStreamNotifier =
        Provider.of<SongStreamNotifier>(context);
    developer.log("Rebuilding Scaffold");
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          types.shuffle();
          final songType = types.first;
          songStreamNotifier.getSongsStream(songType);
        },
      ),
      body: StreamBuilder<QuerySnapshot>(
          stream: songStreamNotifier.songs,
          builder: (context, snapshot) {
            developer.log("Rebuilding stream");
            if (snapshot.hasError) {
              return Text(snapshot.error.toString());
            } else if (snapshot.hasData) {
              return ListView.builder(
                  itemCount: snapshot.data!.size,
                  itemBuilder: (BuildContext ctx, int index) {
                    return Text(snapshot.data!.docs[index].get('name'));
                  });
            } else {
              return Container();
            }
          }),
    );
  }

Notifier is called correctly, I can see all log messages on how build is rerun, but the values do not change. The code of the ChangeNotifier is the following:

class SongStreamNotifier extends ChangeNotifier {
  Stream<QuerySnapshot> stream = Stream.empty();
  final SongService songService = SongService();

  Stream<QuerySnapshot> get songs {
    return stream;
  }

  getSongsStream(String type) {
    developer.log('type: $type');
    stream = songService.getSongs(type);
    notifyListeners();
  }
}

which is pretty straighforward: songService.getSongs filters the songs based on the songType.
I still cannot understand how providers work with updating the state of widgets. How come I see the builder method getting run but the StreamBuilder always fetches the same values?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘和柠 2025-02-14 19:11:37

发现问题是什么。我没有在查询上调用快照,而仅在初始集合引用上调用。在我的存储库中,我做到了:

colRef = _db.collection("songs");
if (type != '') {
    colRef.where('kind', isEqualTo: type);
}
return colRef.snapshots()

虽然我本来应该做的

colRef = _db.collection("songs");
if (type != '') {
    return colRef.where('kind', isEqualTo: type).snapshots();
}
return colRef.snapshots()

,但我不知道科尔弗是不可能的。

Found what the issue was. I didn't call snapshots on the query but only on the initial collection reference. In my Repository i did this:

colRef = _db.collection("songs");
if (type != '') {
    colRef.where('kind', isEqualTo: type);
}
return colRef.snapshots()

while I should have done

colRef = _db.collection("songs");
if (type != '') {
    return colRef.where('kind', isEqualTo: type).snapshots();
}
return colRef.snapshots()

but I didn't know colRef was immutable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文