Flutter StreamBuilder 在加载时删除旧数据

Posted

技术标签:

【中文标题】Flutter StreamBuilder 在加载时删除旧数据【英文标题】:Flutter StreamBuilder removes old data while loading 【发布时间】:2020-11-10 08:22:03 【问题描述】:

目前,我有一个 StreamBuilder 从 Firebase 为群组消息应用程序提取数据。我有一个 snapshot.hasData 检查以确保在显示消息之前有数据。问题是当 setState 重建小部件时,它也会重建 StreamBuilder 导致它在再次完成加载数据之前显示静态 snapshot.hasData == false 内容。这看起来真的很糟糕,因为它加载速度非常快,以至于每次重建时屏幕看起来都会闪烁一秒钟。

如何在数据重新加载时保留数据,使其不会闪烁?

在特定情况下,有什么方法可以阻止 StreamBuilder 重建?

谢谢!

编辑添加的当前代码。

var firebaseStream;
  @override
  void initState() 
    super.initState();
    firebaseStream = Firestore.instance
        .collection('groups')
        .document(groupID)
        .collection('messages')
        .orderBy('date', descending: true)
        .limit(15)
        .snapshots();

StreamBuilder(
  stream: firebaseStream,
  builder: (context, snapshot) 
     if (!snapshot.hasData)
        return Container(
           color: Colors.red,);
        return ListView.builder(

【问题讨论】:

【参考方案1】:

听起来好像是直接在StreamBuilder 流属性中获取数据:

StreamBuilder(
  stream: firebase.getData(),
  ...
)

这个问题是每次调用setState 时都会创建一个新流,并且总是给出一个初始null 值。相反,您应该使用StatefulWidget 并在initState 期间在您的状态中创建一个变量,以便它只运行一次。然后将此变量用作StreamBuilder 中的流属性。这是一个非常简单的例子:

class Example extends StatefulWidget 
  Example(Key key) : super(key: key);

  @override
  _ExampleState createState() => _ExampleState();


class _ExampleState extends State<Example> 
  Stream firebaseData;

  @override
  void initState() 
    super.initState();
    firebaseData = Firebase.fetchData(); //Or whatever function you use
  

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
      stream: firebaseData,
      builder: (BuildContext context, AsyncSnapshot snapshot) 
        if (snapshot.hasData) 
          return Text(snapshot.data);
         else 
          return Loading();
        
      ,
    );
  

【讨论】:

所以我将 firebase.getData() 转移到名为 firebaseStream 的 initState 方法中。我将该变量放入流属性中,现在消息显示,但是一旦状态发生更改,它就会重建 StreamBuilder,现在无限期地保留在 snapshot.hasData == false 内容上。你的意思是我应该为我的流构建器创建另一个有状态的小部件并在我的主文件中调用它? 我的代码的布局与您的示例完全相同,但现在 StreamBuilder 在第一次重建后保留了 snapshot.hasData == false 内容。 StreamBuilder 是一些动画小部件的子组件,如果这有任何改变的话。 对不起,您可以添加您的原始代码吗?如果您直接使用 snapshots() ,实际上您似乎可以直接在 StreamBuilder 中使用它。除非你在别处做一些奇怪的事情,否则看不到我说的能解决它 我在我的问题中添加了相关代码,但如果您需要 codeshare.io/5goxJV StreamBuilder 在第 697 行 initState 为 115,这是我所有的代码(很抱歉) 好的,我检查了你的代码,我看不出任何明显的逻辑错误,但是说真的,把你的代码分成小部件!不要试图一次性完成所有操作!这可能是导致问题的原因,尽管我不知道。我建议您尝试将一个 StreamBuilder 提取到它自己的页面中,并简单地显示其输出以查看它是否仍然存在问题。【参考方案2】:

您是否尝试过使用 snapshot.Connection 状态?

@override
      Widget build(BuildContext context) 
        return StreamBuilder(
          stream: firebaseData,
          builder: (BuildContext context, AsyncSnapshot snapshot) 
            if (snapshot.connectionState == ConnectionState.active && snapshot.hasData) 
final data = snapshot.data;
              return Text(data);
             else if (snapshot.connectionState == ConnectionState.waiting) 
              return Loading(); // OR CircularProgressIndicator()
             else // Handle error here.
          ,
        );
      

【讨论】:

这不会改变我的问题的当前状态。谢谢你。

以上是关于Flutter StreamBuilder 在加载时删除旧数据的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在使用 StreamBuilder 从 firebase 加载数据之前显示红色错误屏幕,如何解决?

Flutter 中的 StreamBuilder 卡在 ConnectionState.waiting 中并且只显示加载标记

Flutter StreamBuilder ListView在流数据更改时不会重新加载

FirebaseStorage + Flutter,streamBuilder?

防止 Flutter StreamBuilder 在 ListView 中复制数据

Flutter Firestore StreamBuilder 最初获得空值