如何避免 streambuilder 执行不必要的时间

How to avoid streambuilder executes unnecessarytimes

我正在尝试显示有效的文档列表,但我读到一个好的做法是管理状态(我目前也在尝试理解)。在这种情况下,每次我使用 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 提供了一个有用的解决方案,他有一个展示解决方案的视频

initState 中初始化您的流,就像这个答案一样:

初始状态不会帮助您避免重建,因为在更改选项卡时 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 implementation

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