0

So half of my application relies quite a bit on Firestore.

Sometimes, it takes quite a long time, like 5000ms or more to load my documents. If it was images or something else maybe I'd understand but it's mainly strings or Ints...

Any ideas on how I could improve this?

Thanks


EDIT: db.collection("usersAuth/${FirebaseAuth.getInstance().uid!!}/KitLists").get().addOnSuccessListener { snapshot ->

        for (document in snapshot.documents) {
            val data = document

            val kitName = data.id
            firstKitList.add(kitName)
        }

       mainListViewAdapter.notifyDataSetChanged()
    }

EDIT2

So, I adapted it, but I have an unresolved error on snapshot.

db.collection("usersAuth/${FirebaseAuth.getInstance().uid!!}/KitLists").addSnapshotListener(object : EventListener<QuerySnapshot> {
        override fun onEvent(@Nullable value: QuerySnapshot, @Nullable e: FirebaseFirestoreException?) {
            if (e != null) {
                Log.w("TAG", "Listen failed.", e)
                return
            }

            for (document in snapshot.documents) {
            val data = document

            val kitName = data.id

            firstKitList.add(kitName)

        }

       mainListViewAdapter.notifyDataSetChanged()
        }
    })

this is the error snapshot error

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
FieJoeKot
  • 11
  • 2
  • You've called that parameter `value` in your code: `@Nullable value: QuerySnapshot`. So you need to call it `value` in the loop too: `for (document in value.documents) {` – Frank van Puffelen Feb 15 '18 at 14:50

1 Answers1

5

If you are using a get() call, you need to know that you are trying to read data over the internet. You cannot compare this operation with an operation of reading an SQLite database, which is stored locally on the disk. The speed of getting the data from Firebase servers depends on the speed of your internet connection and on the amount of data that you are trying to get. So most likely the reason for waiting 5000ms is one of these, or why not both. If the reason is the amount of data, try to optimize your queries or try to get the data in small parts.

If we are speaking about the first attempt to read a document, it might be slower than the subsequent ones, because it has to initiate the internet connection. I know that the Firebase team is trying to improve the performance, but you can't expect 0ms when retrieving data over a network.

One thing that you can do, is to enable offline persistence which will create a local cache for the data that was previously read. But a get() request will first check Firebase servers. If you use an addSnapshotListener(), you'll be able to read the data from the cache instantly, without checking the network.

If you want to listen to a single document, please use the following code:

yourDocumentReference.addSnapshotListener(new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) {
        if (e != null) {
            Log.w(TAG, "Listen failed.", e);
            return;
        }

        if (snapshot != null && snapshot.exists()) {
            Log.d(TAG, "Current data: " + snapshot.getData());
        } else {
            Log.d(TAG, "Current data: null");
        }
    }
});

If you want to listen to multiple documents in a collection, please use the following code:

yourCollectionReference.addSnapshotListener(new EventListener<QuerySnapshot>() {
    @Override
    public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException e) {
        if (e != null) {
            Log.w(TAG, "Listen failed.", e);
            return;
        }

        List<String> cities = new ArrayList<>();
        for (DocumentSnapshot doc : value) {
            if (doc.get("name") != null) {
                cities.add(doc.getString("name"));
            }
        }
        Log.d(TAG, "Current cites in CA: " + cities);
    }
});
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • oh cool thanks. So you're saying to replace all my get() for addSnapshotListener() ? – FieJoeKot Feb 15 '18 at 12:48
  • To read data instantly from the cache, yes. Do you think that my answer helped you? – Alex Mamo Feb 15 '18 at 12:50
  • but I also read data from Firestore. Won't that be a problem? – FieJoeKot Feb 15 '18 at 13:36
  • No, it won't. Did you try id? – Alex Mamo Feb 15 '18 at 13:37
  • Can you check my edit? So I would replace that get() for addSnapshotListener? Is that all? – FieJoeKot Feb 15 '18 at 13:40
  • No, it's incorrect. You cannot simply replace it. This is how you can [get realtime updates](https://firebase.google.com/docs/firestore/query-data/listen). See, you need to use `addSnapshotListener` and implement `onEvent()` method. – Alex Mamo Feb 15 '18 at 13:44
  • Won't that mess the logic I have, on the for loop? Would you mind use my example and show me how I could change that and use the snapshot? Thanks – FieJoeKot Feb 15 '18 at 13:46
  • I'm not used to Kotlin, but as I see you'rr looking to a collection but I wrote you two examples. Please see my updated answer. – Alex Mamo Feb 15 '18 at 13:53
  • I see... I don't know Java. I will try to replicate this in Kotlin and let you know. I need to see also how I am going to replicate my for loop – FieJoeKot Feb 15 '18 at 13:55
  • I think Android Studio can do the replacement for you. Ok, keep me poested. – Alex Mamo Feb 15 '18 at 13:56
  • image uploaded :) – FieJoeKot Feb 15 '18 at 14:03
  • There is no `snapshot.documents` anymore. It's either `snapshot.getData()` as in my first example or `cities.add(doc.getString("name"));` as in my second example. `cities` is as in Firebase official documentation. You need to use your case. – Alex Mamo Feb 15 '18 at 14:06
  • Great. Thanks. I have a question. If cache is empty, with snapshot automatically it is made a request on Internet? @AlexMamo – Federico Rizzo Apr 15 '18 at 18:42
  • @FedericoRizzo Yes, if the chache does not exist, first will create a internet request. – Alex Mamo Apr 23 '18 at 04:23