1

In my app i am using android MVVM architecture, so for retrieving data from cloud firestore i am using layers so i create one more class (FirebaseQueryLiveData) for getting result from firestore. So with my code i am getting the realtime update but not able to add the Cache Source feature of firestore.I want to enable offline mode by adding cache soure. How to add it.

ProductViewModel.java

public class ProductViewModel extends AndroidViewModel {
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private MediatorLiveData<List<ProductModel>> productListLiveData;
private FirebaseQueryLiveData liveData;
 public ProductViewModel(@NonNull Application application) {
        super(application);
    }
public LiveData<List<ProductModel>> getProductList() {
        productListLiveData = new MediatorLiveData<>();
        completeProductList();
        return productListLiveData;
    }
      private void completeProductList() {
     Query query =  db.collection("mainCollection").document("productList")
                .collection("productCollection");
        liveData = new FirebaseQueryLiveData(query);
        productListLiveData.addSource(liveData, new Observer<QuerySnapshot>() {
            @Override
            public void onChanged(QuerySnapshot queryDocumentSnapshots) {
                if (queryDocumentSnapshots!= null){
                    List<ProductModel> productModelList = new ArrayList<>();
                    for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots){
                        ProductModel model = documentSnapshot.toObject(ProductModel.class);
                        productModelList.add(model);                     
                    }productListLiveData.setValue(productModelList);
                }
            }
        });

}

FirebaseQueryLiveData.java

public class FirebaseQueryLiveData extends LiveData<QuerySnapshot> {

    private MyValueEventListener listener = new MyValueEventListener();
    private Query query;
    Source source = Source.CACHE;

    private boolean listenerRemovePending = false;
    private ListenerRegistration registration;
    private Handler handler = new Handler();
    private final Runnable removeListener = new Runnable() {
        @Override
        public void run() {
            registration.remove();
            listenerRemovePending = false;

        }
    };

    public FirebaseQueryLiveData(Query query) {
        this.query = query;
    }

    @Override
    protected void onActive() {
        super.onActive();
        if (listenerRemovePending){
            handler.removeCallbacks(removeListener);
        }else {
          registration=  query.addSnapshotListener(listener);
        }
        listenerRemovePending= false;
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        handler.postDelayed(removeListener, 2000);
        listenerRemovePending=true;
    }

    private class MyValueEventListener implements EventListener<QuerySnapshot> {
        @Override
        public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {
            setValue(queryDocumentSnapshots);
        }
    }
}
Amit Sen
  • 177
  • 2
  • 12
  • Why do you say "not able to add the Cache Source feature"? Firestore has offline persistence enabled by default. – Alex Mamo Dec 10 '18 at 07:04
  • here in this link there is one topic named as **Source Options** in which it explained how to add source cache. so I am trying to implement it. Can u please explain is it not required for android because of offline persistence enabled by default. https://firebase.google.com/docs/firestore/query-data/get-data – Amit Sen Dec 10 '18 at 07:29
  • Ok, I'll write you an answer. – Alex Mamo Dec 10 '18 at 07:36

1 Answers1

1

For Android and iOS, Cloud Firestore has offline persistence enabled by default. This means that your app will work for short to intermediate periods of being disconnected.

And yes, you can specify the source with the help of the DocumentReference.get(Source source) and Query.get(Source source) methods.

By default, get() attempts to provide up-to-date data when possible by waiting for data from the server, but it may return cached data or fail if you are offline and the server cannot be reached. This behavior can be altered via the Source parameter.

So we can now pass as an argument to the DocumentReference or to the Query the source so we can force the retrieval of data from the chache only like this:

FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docIdRef = db.collection("tests").document("fOpCiqmUjAzjnZimjd5c");
docIdRef.get(Source.CACHE).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        //Get data from the documentSnapshot object
    }
});

In this case, we force the data to be retrieved from the cache only but why to use this feature when you say that you want to get realtime updates? So for your use-case I don't see why you would get the data from cache.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thanks a lot for clearing my doubt and I also get the reason in your explanation where to use source and where not to. I got it there is no need to use source as it is realtime update. :-) thanks again. – Amit Sen Dec 10 '18 at 08:26