0
votes

According to Alex Momo's answer, by default, Firestore store documents in cache and load from there, only with new documents or changes it will read again with an additional costs.

I was testing using StreamBuilder and FutureBuilder and I used a print to show me where the data is coming from.

print(document.metadata.isFromCache ? "NOT FROM NETWORK" : "FROM NETWORK");

Even if I use FutureBuilder (.getDocuments()), the first time I open the app it prints "FROM NETWORK", on the second time it loads "FROM NETWORK" again, and database had no changes, so looks like the cache only works when the app is really offline, but it seems if there's connection it will load from server always, does anyone can explain more about that?

The parameter Source.serverAndCache I think is the default and the description says "Causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back toreturning cached data if the server can't be reached.", I think it means: you have connection? loading from server, if not? loading from cache. But that does't help much, since every time we close the app and re open it will load all documents from server again.

FutureBuilder(
            future: Firestore.instance.collection("latest").orderBy("date", descending: true)
                .getDocuments(source: Source.serverAndCache ),
            builder: (context, snapshot) {

              if (!snapshot.hasData || snapshot.data.documents.length == null) {
                return Center(
                  child: CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation(Colors.white),
                  ),
                );
              } else if(snapshot.data.documents.length == 0) {

                return Center(
                    child: Padding(
                      padding: const EdgeInsets.only(left: 16, right: 16),
                      child: Text(
                        "Sorry but there's no wallpapers for this character yet!",
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w300,
                        ),
                        textAlign: TextAlign.center,
                      ),
                    )
                );

              } else {

                return GridView.builder(
                    itemCount: snapshot.data.documents.length,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      childAspectRatio: screenHeight / screenWidth * 0.4,
                      mainAxisSpacing: 1.0,
                      crossAxisSpacing: 1.0,
                    ),
                    itemBuilder: (context, index) {

                      return _buildGrid(snapshot.data.documents[index], index);

                    }
                );



              }
            }
          )

Widget _buildGrid(DocumentSnapshot document, int index) {

      print(document.metadata.isFromCache ? "NOT FROM NETWORK" : "FROM NETWORK");

      return GestureDetector(
        child: Hero(
          tag: index,
          child: CachedNetworkImage(
            imageUrl: document['url'],
            errorWidget: (context, url, error) => Icon(Icons.error_outline),
            fit: BoxFit.fill,
            filterQuality: FilterQuality.low,

          ),

        ),
        onTap: () {
          Navigator.of(context).push(
              MaterialPageRoute(
                  builder: (context) => DetailScreen(document['url']))
          );
        },
      );
    }
1
That is the correct behaviour - Peter Haddad
If you are offline a local copy will be created and any database write that is done while you are offline will be synced when you are online again. But then data will still be retrieved from the server - Peter Haddad

1 Answers

0
votes

Peter's comments are correct. Any time you call .getDocuments(source: Source.serverAndCache ), Firestore will need to check against the server to see if the data is modified. And since this requires the server to read the documents, you will be charged for those reads.

If you want to force Firestore to read from its local cache, use .getDocuments(source: Source.Cache). That means you run the risk of showing stale data, but that's a trade-off you'll have to make.

I typically recommend using onSnapshot listeners, as they are better suited for sending only the changes from the server to the client.

Also check out: