1

I'm creating an Android app with an activity with a bottom navigation control that lets the user navigate between different fragments. In these fragments i have lists of data coming from a firebase backend that i show with a RecyclerView. The problem is that every time i navigate between these fragments all the data is downloaded again, while i would want to use cached data and just listen for changes.

What i have done so far is to use ViewModel and LiveData and they work fine. Moreover if i disconnect the phone from the Internet the data is showed (and of course is not downloaded), even if i navigate between the fragments.

In the fragment that shows the data i have:

LiveData<List<UncompletedTask>> taskLiveData = viewModel.getTaskLiveData();
taskLiveData.observe(this, new Observer<List<UncompletedTask>>() {
    @Override
    public void onChanged(List<UncompletedTask> uncompletedTasks) {
        myAdapter.submitList(uncompletedTasks);
        listener.onTodoListElementsLoaded(uncompletedTasks.size());
    }
});

In the viewmodel i have:

private TodoTaskRepository repository;
@NonNull
public LiveData<List<UncompletedTask>> getTaskLiveData() {
    return repository.getTaskLiveData();
}

In the TodoTaskRepository i initialize FirebaseQueryLiveData in the contructor and return it in getTaskLiveData(). Finally FirebaseQueryLiveData is like this:

public class FirebaseQueryLiveData extends LiveData<DataSnapshot> {
    private static final String LOG_TAG = "FirebaseQueryLiveData";

    private final Query query;
    private final MyValueEventListener listener = new MyValueEventListener();

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

    @Override
    protected void onActive() {
        query.addValueEventListener(listener);
    }

    @Override
    protected void onInactive() {
        query.removeEventListener(listener);
    }

    private class MyValueEventListener implements ValueEventListener {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            setValue(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e(LOG_TAG, "Can't listen to query " + query, databaseError.toException());
        }
    }
}

How can i download all the data the first time but then just listen for changes and don't download the same data while navigating between fragments if nothing is changed?

Marco Cadei
  • 145
  • 2
  • 4
  • 14

1 Answers1

1

If you have enabled disk persistence then data will not be download again unless data has changed

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

When you run your ValueEventListener the first time data is downloaded alright, the second time the same ValueEventListener runs then data is coming from local cache persistent

Moreover if disconnect the phone from the Internet the data is indeed coming from the same local cache.

Erik
  • 5,039
  • 10
  • 63
  • 119
  • Hi thank you for your answer! Even using `FirebaseDatabase.getInstance().setPersistenceEnabled(true);` data gets downloaded every time because in `FirebaseQueryLiveData` if there are no more listener (ie, i change fragment) the listener is removed and then re-added when i go back to the same fragment. However i think this is the right thing to do (read here: https://firebase.googleblog.com/2017/12/using-android-architecture-components.html), but how can i avoid to download the data every time in this case? – Marco Cadei May 22 '19 at 19:19
  • If Persistence is enabled the same data is never downloaded again unless you have uninstalled the app, dunno how you think.. – Erik May 22 '19 at 19:37
  • I have placed a `Log.d` call inside `onDataChange` of `MyValueEventListener` and it fires every time i navigate to the fragment. Doesn't that mean the same is downloaded again? – Marco Cadei May 22 '19 at 19:40
  • It is not downloaded again, it is grabbed from the disk persistent DATA on the phone(cache) When you add the `addValueEventListener` it will always fire even if you have internet or not, this is the great thing, User can use the app even is no Internet. When Internet exist the app is syncing data with backend Firebase – Erik May 22 '19 at 19:46
  • Okay thank you a lot! One last doubt: i get that when there's no internet the app uses cached data (because it works, so that must be true), but is that true also when there's internet connection? I mean: if i have internet on but `FirebaseDatabase.getInstance().setPersistenceEnabled(true);` set i do NOT download the same data even if i have internet, am i right? – Marco Cadei May 22 '19 at 19:51
  • Yes your right, Read about it here, [Enabling Offline Capabilities on Android](https://firebase.google.com/docs/database/android/offline-capabilities) – Erik May 22 '19 at 19:54