0

I'm developing an Android application that uses a lot data from and towards my Firestore database.

Here is an overview of what I do.

  1. Uses from: I set up listeners on documents and collections, and I use the method get ;

  2. Uses towards: I store documents, using and not using set, I also update documents.

For now, each time I do any of these mentionned actions, I instanciate a class named SetupFirebaseFirestore. This is an AsyncTask which instanciates Firestore. When it's finished, it also executes a callback (given when I instanciate SetupFirebaseFirestore).

You can find the code below:

public class SetupFirebaseFirestore extends AsyncTask<Void, Void, Void> {    
    private SetupFirebaseFirestorePostExecuteCallback post_execute_callback;
    private FirebaseFirestore db;

    public SetupFirebaseFirestore(SetupFirebaseFirestorePostExecuteCallback callback) {
        post_execute_callback = callback;
    }

    private void createFirebaseProducts() {
        db = FirebaseFirestore.getInstance();
        db.setFirestoreSettings(new FirebaseFirestoreSettings.Builder()
                .setTimestampsInSnapshotsEnabled(true)
                .build());
    }

    @Override
    protected Void doInBackground(Void[] params) {
        createFirebaseProducts();
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        post_execute_callback.onTaskCompleted(db);
    }
}

The problem and The question

The problem is that my application interacts a lot with Firestore. So there are many instanciations of Firestore, and thus many RAM consumption.

By the way, perhaps it overloads Firestore since I call getInstance() and build()?

How could I do something more clean in terms of RAM consumption? Should I use singleton pattern? It would allow me to instanciate Firestore once, and the same for building its settings.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
JarsOfJam-Scheduler
  • 2,809
  • 3
  • 31
  • 70

1 Answers1

1

The Firebase database client, already runs all network operations in a background thread. This means that all operations take place without blocking your main thread. Putting operations in an AsyncTask does not give any additional benefits. Further more, instantiating the FirebaseFirestore object inside it, will not help you at all. When you interact with the Cloud Firestore database, a socket connection between your app and the Firebase servers is opened. From that moment on, all traffic between the app and the database goes over that same socket. So it doesn't matter how many times you call getInstance(), you'll always have a single connection.

If there are no active listeners for a period of time, the Cloud Firestore client will automatically close the connection but it will re-open the connection when you attach a listener or perform a read/write operation again.

So, it doesn't matter how many times you are getting the connection or how many listeners you have, it matters how much data you are processing on the client side. And to answer your question:

How to interact with Firestore in order to reduce RAM consumption on client side?

Reduce the number of documents that you get in a single query. The query performance depends on the number of items you request and not of the number of items your request them from. To get data in smaller chunks, please see:

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Hi, sorry for answering late, I was at work. Very clear answer. So I can have only one instanciated object of Firestore (being its sole instance at any time of execution), in my class, using the singleton pattern? The connections will close automatically, **but also re-open automatically**. So there won't be any problem of network if I use a single instance, created only once in my application (ex: connection to DB lost). BTW I shouldn't use an asynchronous task. Am I right all along? I will edit my question with updated code, to be sure I correctly followed your explanations. – JarsOfJam-Scheduler Feb 12 '19 at 20:20
  • 1
    Yes, you'll only have a single `FirebaseFirestore` object by simply calling `FirebaseFirestore.getInstance()`. The connections will not close automatically unless you are using a `get()` call. If you are listening for realtime updates, the [listener should be removed](https://stackoverflow.com/questions/48699032/how-to-set-addsnapshotlistener-and-remove-in-populateviewholder-in-recyclerview/). No, shouldn't use an `AsyncTask` at all. There is no need for that. – Alex Mamo Feb 12 '19 at 21:33
  • Should I call build settings each time I call getInstance, or not? Perhaps not, if I put this instance in a static class? When the get() call ends, yes it will close the connection but the latter will be reopened when needed (listener, update, get, etc.)? – JarsOfJam-Scheduler Feb 12 '19 at 21:36
  • 1
    No, there is also no need for that. Yes, you can put the creation of the `FirebaseFirestore` object in a helper class. When the get() call ends, the listener is removed. If you need to listen for realtime updated, see [get realtime updates with Cloud Firestore](https://firebase.google.com/docs/firestore/query-data/listen). – Alex Mamo Feb 12 '19 at 22:17