在我的Flutter应用程序中,有一个可通过按钮访问的自定义抽屉.在这个抽屉里,有一个小部件(InfoCard),它显示了一些用户的信息.然而,在这个小部件中,有一个FutureBuilder,所以每次显示抽屉时都会显示一个CircularProgressIndicator,直到它从Firerestore服务器获得所有信息.我的问题是:我可以避免FutureBuilder,这样当应用程序完全加载时,它就可以获得小部件所需的所有数据吗?

与此相关的另一个问题是,我需要等待Firestore数据库加载后才返回InfoCard小部件(我不知道为什么,因为当应用程序启动时所有的数据都已经加载了).所以问题是:我必须避免调用数据库,或者在构建小部件之前以某种方式调用它,这样我就不需要使用FutureBuilder了.

下面是小工具抽屉:

class SideDrawer extends ConsumerStatefulWidget {
  SideDrawer({
    super.key,
    required this.setIndex,
  });

  Function(int index) setIndex;

  @override
  ConsumerState<SideDrawer> createState() => _SideDrawerState();
}

class _SideDrawerState extends ConsumerState<SideDrawer> {
  @override
  Widget build(BuildContext context) {
    final userP = ref.watch(userStateNotifier);

    return Scaffold(
      body: Container(
        width: MediaQuery.sizeOf(context).width * 3 / 4,
        height: double.infinity,
        color: Theme.of(context).colorScheme.secondary,
        child: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              FutureBuilder<Widget>(
                future: Datas().infocard(userP),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done) {
                    if (snapshot.hasError) {
                      return Text('Errore: ${snapshot.error}');
                    }
                    return snapshot.data!;
                  } else {
                    return CircularProgressIndicator();
                  }
                },
              ),
              ColDrawer(setIndex: (index) {
                widget.setIndex(index);
              },),
            ],
          ),
        ),
      ),
    );
  }
}

infoCard方法:

Future<Widget> infocard(AppUser userP) async {
    var db = FirebaseFirestore.instance;
    QuerySnapshot qn =
        await db.collection('users').where('id', isEqualTo: userP.id).get();
    return InfoCard(
      username: userP.username,
      age: userP.age,
      weight: userP.measurements
          .firstWhere((measure) => measure.title == 'Weight')
          .datas
          .last
          .values
          .first,
    );
  }

如果我不等待数据库被加载,或者如果我用InfoCard小部件替换FutureBuilder,它只会为userP.measurements.线路:

StateError (Bad state: No element)

最后,为什么我需要调用数据库,即使应用程序在Firestore数据库上启动时已经加载了所有数据?

推荐答案

每次用户点击访问抽屉时,都会在Firestore中创建一个get()调用.这意味着您必须支付的读取次数等于每次显示抽屉时查询返回的文档数量.

我不知道为什么,因为所有的数据都已经加载时应用程序启动.

该市场并不自由当你调用get()时,你总是从Firebase服务器获取数据,除非你显式调用specify the source,所以你只能从缓存中读取数据.

但是,你可以附加一个persistent listener,这样你就可以获得实时更新.我也建议阅读以下博客文章,以更好地理解:

与此相关的另一个问题是,在返回InfoCard小部件之前,我需要等待Firestore数据库加载.

所有Firebase数据库调用都是异步的,因此您需要等待直到数据可用.不幸的是,你没有什么可以做的来加快事情.

Flutter相关问答推荐

build_runner显示错误没有为类ClassDeclaration定义getter宏关键字'

Flutter 布局-全屏幕容器

在Flutter 中创建自定义Snackbar类

Flutter creating Constant.dart InputDecoration section put pass in hintText

Flutter 翼future 建造者不断开火和重建.它在每次重建时都会生成一个新的随机数--我如何防止这种情况?

在Fighter中,我如何在窗口的顶部和底部排列Widget?

如何在Date Time类中只显示日期?

任务';:app:check DebugDuplicateClasss';的Ffltter Share_plus抛出执行失败

在带有 flutter 的 Native Android 中,EventChannel.EventSink 始终为 null

如何在Flutter 中使用选定的键和值从 map 列表创建 map

如何在flutter中将所有单词的第一个字母大写

无状态小部件被奇怪地重建

更改下拉按钮的背景 colored颜色 - flutter

如何设置行中项目之间的空格相等?

如何将行推到列的底部

如何在向下滚动时隐藏顶部卡片并在向上滚动时出现?

SfCircularChart 周围的额外间距

Flutter - 使用 pin 进行身份验证

Flutter Firestore 数据库排序最近 24 小时内最喜欢的文档

如何在Flutter 中专注于列表视图中最新添加的项目