Using Offline Persistence in Firestore in a Flutter App

16,801

Solution 1

when you use offline persistence in Firestore, don't use Transactions or await for response.

so, change this :

  await Firestore.instance.collection('certificados').document((certID.toString()))
      .setData(finalDataMap);

to this:

 Firestore.instance.collection('certificados').document((certID.toString()))
      .setData(finalDataMap);

When you restore your internet connection your data will be sync automatically, even if you are in background.

Doesn't work when your app is closed.

Context Of Promises & Callbacks when Offline

Why the above code change to remove "await" works.

Reference: Firebase Video - How Do I Enable Offline Support 11:13

Your callback won't be called and your promise won't complete until the document write has been successful on the server. This is why if your UI waits until the write completes to do something, it appears to freeze in "offline mode" even if the write was actually made to the local cache.

It is OK to not use async / await, .then() or callbacks. Firestore will always "act" as if the data change was applied immediately, so you don't need to wait to be working with fresh data.

You only need to use callbacks and promises when you need to be sure that a server write has happened, and you want to block other things from happening until you get that confirmation.

Solution 2

I think the currrent answer is outdated. According to the firebase documentation, offline persistentence is enabled by default for Android and iOS. For the web, it is not.

In flutter, the firestore implementation is based on the underlying OS. So you're safe on mobile apps, but not with flutter for web.

Solution 3

It is enabled by default but still only when you are not using await or transactions, further you can use timeout to stop listening to network connection by firestore after a specific time.

 ref.setData(newNote.toMap()).timeout(Duration(seconds: 2),onTimeout:() {

        //cancel this call here

        print("do something now");
      });
Share:
16,801
Brenno Fagundes
Author by

Brenno Fagundes

Updated on June 06, 2022

Comments

  • Brenno Fagundes
    Brenno Fagundes about 2 years

    I'm developing a app that uses Firebase's Firestore to send data to the web. One of the functions of the app is being able to save data in the device while being offline and send it to Firestore when internet connection is restored. I activated offline persistence but it dosen't work.

    DEBUG CONSOLE:

    W/OkHttpClientTransport(28536): Failed closing connection
    W/OkHttpClientTransport(28536): javax.net.ssl.SSLException: Write error: ssl=0x7f7acfc408: I/O error during system call, Broken pipe
    W/OkHttpClientTransport(28536):     at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_write(Native Method)
    W/OkHttpClientTransport(28536):     at com.google.android.gms.org.conscrypt.NativeSsl.write(:com.google.android.gms@[email protected] (040406-222931072):4)
    

    How can I activate offline persistence and sync with Firestore when internet is restored?

    MY CODE:

    Future<Null> sendFirebaseData(var selectedModel) async {
    
        Firestore.instance.enablePersistence(true);
        var certID = await getIDCertificado();
    
        var dateTime = new DateTime.now();
        var nowHour = new DateFormat('kk:mm:ss').format(dateTime);
    
          Map<String, dynamic> dataHeader = {
            'ID':                certID,
            };
    
          Map<String, dynamic> finalDataMap = {}..addAll(dataGeneral)
                                              ..addAll(dataInstrumento)..addAll(dataPadrao)
                                              ..addAll(dataAdicional)..addAll(dataHeader);
    
          await Firestore.instance.collection('certificados').document((certID.toString()))
              .setData(finalDataMap);}
    
    • bizz84
      bizz84 almost 5 years
      Note that "Firestore.instance.enablePersistence(true);" is now deprecated. You should call "Firestore.instance.settings(persistenceEnabled: true);" instead.
  • Rohan Taneja
    Rohan Taneja about 5 years
    Thanks! What would be the equivalent version for this on Flutter web?
  • FilipeOS
    FilipeOS almost 5 years
    So in a chat app this still apply? replace all the "transactions" and remove await?
  • Ride Sun
    Ride Sun almost 5 years
    I really had a hard time finding this. I am also wondering why this is not handled transparently?
  • Ride Sun
    Ride Sun almost 5 years
    Whats about the get access - any changes there?
  • Mehmet
    Mehmet over 4 years
    no, the answer is updated. I just tried without await keyword and it worked. It is not using offline database with await keyword.
  • Mehmet
    Mehmet over 4 years
    Thanks! It is worked when I removed the await keyword :)
  • F.O.O
    F.O.O about 4 years
    @diegoveloper why does it not work when app is closed?
  • giorgio79
    giorgio79 about 4 years
    This answer is fantastic Why is not Flutter firestore docs contain this info explicitly.
  • Jonas
    Jonas almost 4 years
    But what do I do if I need to await to get access to the Id of the DocumentSnapshot?
  • Brandon Pillay
    Brandon Pillay over 3 years
    Can the .then() callback function still be used offline?