如何在Flutter中获取异步快照的元数据

发布于 2025-01-15 21:41:24 字数 2674 浏览 0 评论 0原文

因此,我从 Cloud Firestore 中提取数据,但在检查是否通过缓存或服务器检索数据时有点卡住了。因此,要在这里执行此操作,我将如何从云 Firestore 中提取数据

marketplacedata() async {
    try {
      var snapshot = await FirebaseFirestore.instance
          .collection('marketplaces')
          .doc('All')
          .collection('offers')
          .get();

,我将从 init 中提取数据,

class _SearchMarketplaceState extends State<SearchMarketplace> {
  void initState() {
    widget.futuredata = getData();
    super.initState();
  }

  getData() async {
    return await FireStoreData().marketplacedata('All');
  }

然后我将使用未来的构建器来检索数据,因此

FutureBuilder(
                future: widget.futuredata,
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  var marketplacedata = snapshot.data;

                  if (snapshot.hasError) {
                    return Text('something went wrong');
                  }

                  **if (snapshot.hasData) {
                    HOW DO I CHECK WHETHER THE DATA IS COMING FROM CACHE?);
                    .metadata doesnt work on AsyncSnapShot


                  }**

                  if (searchController.text.isNotEmpty) {
                    marketplacedata = searchFilter(
                        searchController.text.toLowerCase(), marketplacedata);
                  }
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return Loading();
                  } else {
                    return GridView.builder(
                      gridDelegate:
                          const SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 3,
                        childAspectRatio: (4 / 4),
                      ),
                      itemCount: marketplacedata.length ?? 1,
                      itemBuilder: (BuildContext context, int index) {
                        return buildMarketplace(context, index,
                            marketplaceID: marketplacedata[index].marketplaceID,
                            heading: marketplacedata[index].heading,
                            companyDesc: marketplacedata[index].companyDesc,
                            iconURL: marketplacedata[index].iconURL,
                            keywords: marketplacedata[index].keywords,
                            preferred: marketplacedata[index].preferred,
                            imgURL: marketplacedata[index].imgURL);
                      },
                    );
                  }
                },
              ),

我们将不胜感激。最后,我试图最大限度地减少读取次数,并希望从缓存中读取大部分数据。但是我似乎无法访问任何数据。提前致谢。

So I am pulling data from Cloud Firestore but a bit stuck on checking to see whether the data is being retrieved via the cache or server. So to do this here is how I am pulling the data from cloud firestore

marketplacedata() async {
    try {
      var snapshot = await FirebaseFirestore.instance
          .collection('marketplaces')
          .doc('All')
          .collection('offers')
          .get();

I'm pulling the data from the init

class _SearchMarketplaceState extends State<SearchMarketplace> {
  void initState() {
    widget.futuredata = getData();
    super.initState();
  }

  getData() async {
    return await FireStoreData().marketplacedata('All');
  }

Then I am using future builder to retrieve the data as such

FutureBuilder(
                future: widget.futuredata,
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  var marketplacedata = snapshot.data;

                  if (snapshot.hasError) {
                    return Text('something went wrong');
                  }

                  **if (snapshot.hasData) {
                    HOW DO I CHECK WHETHER THE DATA IS COMING FROM CACHE?);
                    .metadata doesnt work on AsyncSnapShot


                  }**

                  if (searchController.text.isNotEmpty) {
                    marketplacedata = searchFilter(
                        searchController.text.toLowerCase(), marketplacedata);
                  }
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return Loading();
                  } else {
                    return GridView.builder(
                      gridDelegate:
                          const SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 3,
                        childAspectRatio: (4 / 4),
                      ),
                      itemCount: marketplacedata.length ?? 1,
                      itemBuilder: (BuildContext context, int index) {
                        return buildMarketplace(context, index,
                            marketplaceID: marketplacedata[index].marketplaceID,
                            heading: marketplacedata[index].heading,
                            companyDesc: marketplacedata[index].companyDesc,
                            iconURL: marketplacedata[index].iconURL,
                            keywords: marketplacedata[index].keywords,
                            preferred: marketplacedata[index].preferred,
                            imgURL: marketplacedata[index].imgURL);
                      },
                    );
                  }
                },
              ),

Any help is appreciated. In the end I am trying to minimize the number of reads I am getting and hoping to get most of the data read from the cache. However I cant seem to access any data. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彩扇题诗 2025-01-22 21:41:24

您可以使用 data 属性FutureBuilder 中的快照来访问元数据属性:

snapshot.data?.metadata.isFromCache

但是,由于您的总体目标是减少后端调用,因此对 Firestore 的 get() 调用将始终首先从服务器获取。请参阅 get()

Source.serverAndCache(默认值)会导致 Firestore 尝试检索最新(服务器检索的)快照,但如果无法访问服务器,则回退到返回缓存数据。

您可以有条件地使用 Future 从 Firestore 缓存中获取,如果没有缓存数据,则随后从服务器中获取:

  Future<DocumentSnapshot> getData(Source dataSource) {
    return FirebaseFirestore.instance
        .collection("users")
        .doc("testUser1")
        .get(GetOptions(source: dataSource)); //calls using GetOptions with Source parameter
  }
//using a nested FutureBuilder
return FutureBuilder<DocumentSnapshot>(
      future: getData(Source.cache), //first restricts to local cache
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> cacheSnap) {
        if (cacheSnap.hasError ||
            !cacheSnap.hasData ||
            !cacheSnap.data!.exists) {
          return FutureBuilder(
              future: getData(Source.server), //nested Future uses the server
              builder: (BuildContext context,
                  AsyncSnapshot<DocumentSnapshot> serverSnap) {
                if (serverSnap.connectionState == ConnectionState.done) {
                  return Text(
                      "Server Future: ${serverSnap.data?.metadata.isFromCache}");
                }

                return Text("Loading");
              });
        }

        if (cacheSnap.connectionState == ConnectionState.done) {
          return Text("Cache Future: ${cacheSnap.data?.metadata.isFromCache}");
        }

        return Text("loading");
      },
    );

如果您想收听实时更新,则 初始状态可以来自缓存:

如果本地缓存中有可用状态,查询快照将首先使用缓存数据填充,然后在客户端赶上服务器状态时使用服务器数据进行更新。

在 Flutter 中,您可以使用 StreamBuilder 如果你想走这条路,而不是 FutureBuilder 。我在我的项目中证实了这种行为。

You can use the data property of the snapshot in your FutureBuilder to access the metadata property:

snapshot.data?.metadata.isFromCache

However, since your overall goal is to reduce backend calls, your get() call to Firestore will always fetch from the server first. See the default value of source in the GetOptions argument to get():

Source.serverAndCache (default value), causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back to returning cached data if the server can't be reached.

You could conditionally use your Future to fetch from the Firestore cache, and subsequently from the server if there is no cached data:

  Future<DocumentSnapshot> getData(Source dataSource) {
    return FirebaseFirestore.instance
        .collection("users")
        .doc("testUser1")
        .get(GetOptions(source: dataSource)); //calls using GetOptions with Source parameter
  }
//using a nested FutureBuilder
return FutureBuilder<DocumentSnapshot>(
      future: getData(Source.cache), //first restricts to local cache
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> cacheSnap) {
        if (cacheSnap.hasError ||
            !cacheSnap.hasData ||
            !cacheSnap.data!.exists) {
          return FutureBuilder(
              future: getData(Source.server), //nested Future uses the server
              builder: (BuildContext context,
                  AsyncSnapshot<DocumentSnapshot> serverSnap) {
                if (serverSnap.connectionState == ConnectionState.done) {
                  return Text(
                      "Server Future: ${serverSnap.data?.metadata.isFromCache}");
                }

                return Text("Loading");
              });
        }

        if (cacheSnap.connectionState == ConnectionState.done) {
          return Text("Cache Future: ${cacheSnap.data?.metadata.isFromCache}");
        }

        return Text("loading");
      },
    );

If you want to listen to real time updates, then the initial state can come from the cache:

If there is a state available in a local cache, the query snapshot will be initially populated with the cached data, then updated with the server's data when the client has caught up with the server's state.

In Flutter, you would use a StreamBuilder instead of a FutureBuilder if you want to go this route. I confirmed this behavior in my project.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文