【问题标题】:Flutter: StreamBuilder with FirebaseFlutter:带有 Firebase 的 StreamBuilder
【发布时间】:2022-02-16 23:45:13
【问题描述】:

我有来自Firebase 的对象的ListView,我希望在数据更改时使用StreamBuilder 刷新它。

我可以很好地加载我的列表,并且当数据更改时我的列表会刷新。

我遇到的问题不是刚刚更新更改的ListTile,而是我看到该图块被复制,因此我看到了新更改和旧更改。

这是我的设置:

final ref = FirebaseDatabase.instance.reference();
late DatabaseReference itemRef;
late FirebaseDatabase database = FirebaseDatabase();
late StreamSubscription _objectInfoStreamSub; // Not sure if needed?
late List<CustomObject> data = [];

@override
  void initState() {
    super.initState();

    final keys = Global.kData.keys;

    for (final key in keys) {
      // Initialize this...
      itemRef = database.reference().child('ABC').child(key.toString());
    }

    // Load the data...
    _setListeners();
}

// Here is where I load my data initially...
Future<void> _setListeners() async {
    // Clear out our data before we reload...
    data.clear();

    final keys = Global.kData.keys;

    for (final key in keys) {
      _objectInfoStreamSub =
          ref.child("ABC").child(key.toString()).onValue.listen(
        (event) {
          setState(() {
            // Mapped the data...
            final firebaseData = Map<String, dynamic>.from(event.snapshot.value);

            // Create the Room...
            final room = CustomObject.fromJson(firebaseData);

            // Check if blocked...
            // Logic to see if user is blocked
            
            // check if isArchived
            // Logic to see if room is archvied

            if (!isBlocked && !isArchived) {
              if (!data.contains(room)) {
                data.add(room);
              }
            }

            // Sort by date
            // Logic to sort so the most recent is at top
          });
        },
      );
    }
}

// Here is my updated StreamBuilder...
SliverToBoxAdapter(
  child: StreamBuilder<dynamic>(
    stream: itemRef.child('ABC').onValue,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return Center(
          child: CircularProgressIndicator(),
        );
      }
      if (snapshot.hasData &&
                        snapshot.connectionState == ConnectionState.active) {
        return ListView.builder(
          physics: NeverScrollableScrollPhysics(),
          shrinkWrap: true,
          itemCount: data.length,
          itemBuilder: (BuildContext context, int index) {
            return ChatRoom(
              data: data[index],
            );
          },
        );
      } else {
        return Container();
      }
    },
  ),
),

【问题讨论】:

  • 如果您使用 List data 显示在 CustomListTile 上,那么您不应该依赖 StreamBuilder 的快照吗?目前尚不清楚List data 是如何从您提供的代码 sn-p 更新的。
  • 您确定,您在 Firebase 上没有重复数据,对吧?
  • 正确。我有一个刷新按钮,如果我点击它,它会将我的 ListView 重置为正常。在被调用的方法中,我正在清除数据并再次获取它。所以,我的流构建器中的某些东西并没有做同样的事情。它只是看到有新的东西并添加它而不是找到正确的行并更新该行。
  • 我已经更新了上面的代码。

标签: flutter listview firebase-realtime-database stream-builder


【解决方案1】:

不确定这是否会导致您的问题,但请尝试用StreamBuilder 包装ListView.builder() 而不仅仅是它的项目。因为在您当前的代码状态下,如果您添加另一个项目并且您的 data.length 会更改,ListView.builder() 将不会被重建,也不会构建新数据。

【讨论】:

  • 我的问题是,我是否需要这样做 -> .child(data[index].toString()) 如果是这样,那么我将如何获取该项目的索引?我之前尝试过相反的方法,但也看到了相同的结果。
  • 之前我刚刚厌倦了 itemRef.onValue 作为流
  • 我认为您需要itemRef.child('ABC').onValue 将其用作流,如果这不起作用,请提供代码您的dataitemRef 是如何初始化的
  • 我已经更新了上面的代码。
  • 当你使用itemRef.child('ABC').onValue作为流时,输出是否和以前一样?它工作正常吗?
猜你喜欢
  • 2021-09-30
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 2022-08-19
  • 2021-09-13
  • 2020-12-14
  • 2020-10-13
  • 2023-01-12
相关资源
最近更新 更多