首页 > 解决方案 > 如何避免streambuilder执行不必要的时间

问题描述

我正在尝试显示有效的文档列表,但我读到一个好的做法是管理状态(我目前也在尝试理解)。在这种情况下,每次我使用 bottomNavigationBar 更改屏幕时,streamBuilder 都会执行(我总是看到 CircularProgressIndicator)。我尝试在 intState 中调用集合引用,但仍然是同样的问题,我的代码:

class Deparments extends StatefulWidget {
  Deparments({Key? key, required this.auth}) : super(key: key);
  final AuthBase auth;

  @override
  _DeparmentsState createState() => _DeparmentsState();
}

class _DeparmentsState extends State<Deparments> {
  late final Stream<QuerySnapshot<Object?>> _widget;

 Stream<QuerySnapshot<Object?>> getProds(){
   CollectionReference ref =  FirebaseFirestore.instance.collection("Departamentos");
   return ref.snapshots();
 }
  @override
  void initState() {
    super.initState();
    _widget = getProds();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: SideMenu(auth: widget.auth),
      appBar: AppBar(
        title: Text("Departamentos"),
        centerTitle: true,
        backgroundColor: Colors.green,
      ),
      body: Container(
        child: StreamBuilder<QuerySnapshot> (
            stream: _widget,
            builder: (BuildContext context, snapshot) {
              if (!snapshot.hasData) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else {
                List deparments =
                    snapshot.data!.docs.map((doc) => doc.id).toList();
                return Column(
                  children: [
                    Expanded(
                      child: ListView.builder(
                          padding: EdgeInsets.only(top: 10),
                          scrollDirection: Axis.vertical,
                          itemCount: deparments.length,
                          itemBuilder: (context, index) {
                            return SingleChildScrollView(
                              child: Card(
                                child: Text(deparments[index]),
                              ),
                            );
                          }),
                    )
                  ],
                );
              }
            }),
      ),
    );
  }
}

更新:对于那些面临同样问题的人,Tayan 提供了一个有用的解决方案,他有一个显示解决方案的视频https://stackoverflow.com/a/64057210/9429407

标签: flutterstream-builderflutter-state

解决方案


初始化状态不会帮助您避免重建,因为在更改选项卡时 Flutter 会重建您的屏幕。所以我们需要一些方法来让我们的屏幕保持活跃,所以这里出现了 AutomaticKeepAliveClientMixin。

class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin<Home> {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {

    //Make sure to include the below method
    super.build(context);

    return SomeWidget();
  }
}

上述实现使您的所有选项卡状态保持不变,并且不会再次重建选项卡。好吧,这可能会达到您的目的,但它可能不会空闲,因为即使用户实际上没有访问过标签,这也会一次加载所有标签,因此要避免构建,除非单击标签,请结合综合浏览量使用上述方法。

查看pageView 实现

此外,如果您想要一种更好的方法来管理状态并将一些读取调用保存到 Firestore,那么您应该在本地存储数据并仅获取那些需要的数据和/或使用分页。


推荐阅读