Since I'm new to programming Android apps I followed a tutorial on how to use the Android Architecture Components and Firebase for implementing the MVVM (using LiveData, ViewModel, etc.).
The tutorial I followed can be found here:
I'm now left with what I think is a decent implementation of the MVVM, but I can not wrap my head around how I am supposed to pass query parameters to it. Right now I need to hardcode the ID of the document I want to retrieve:
public class AlarmDAO {
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
public AlarmLiveData getFirestoreLiveData() {
DocumentReference documentReference = firebaseFirestore.collection(Collection.ALARMS.name).document("5RxJNuNyhDJlz49wpBkw");
return new AlarmLiveData(documentReference);
}
}
That then gets called by a class extending ViewModel
.
public class AlarmViewModel extends ViewModel {
private AlarmDAO DAO = new AlarmDAO();
private AlarmLiveData liveData = null;
public LiveData<Alarm> getAlarmLiveData() {
liveData = DAO.getFirestoreLiveData();
return liveData;
}
public LiveData<Alarm> getAlarm() {
return liveData.alarm;
}
}
And then I observe that data in my activity:
model.getAlarmLiveData().observe(this, Observable -> {});
model.getAlarm().observe(this, alarm -> {
if (alarm != null) {
alarmTextView.setText(alarm.getTest());
else {
Log.d(TAG, "Waiting for data");
}
});
My problem is that I do not see a way of querying for a specific alarm. For instance model.getAlarm("someId")
. I am under the impression that it should be done in the DAO and/or the ViewModel, but I can't figure out how. Another thing I do not understand is why I need to observe both model.getAlarmLiveData()
and model.getAlarm()
in my activity, as using only one does not work. The answer to both of those questions is most likely very simple, but thus far I haven't been able to figure it out.
For completeness: the Alarm
class is nothing besides a getter and setter for two strings, and the AlarmLiveData
class is below.
public class AlarmLiveData extends LiveData<Alarm> implements EventListener<DocumentSnapshot> {
private static final String TAG = AlarmLiveData.class.getSimpleName();
private Alarm alarmTemp = new Alarm();
private DocumentReference documentReference;
private ListenerRegistration listenerRegistration = () -> {};
public MutableLiveData<Alarm> alarm = new MutableLiveData<>();
public AlarmLiveData(DocumentReference documentReference) {
this.documentReference = documentReference;
}
@Override
protected void onActive() {
listenerRegistration = documentReference.addSnapshotListener(this);
super.onActive();
}
@Override
protected void onInactive() {
listenerRegistration.remove();
super.onInactive();
}
@Override
public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) {
if (documentSnapshot != null && documentSnapshot.exists()) {
alarmTemp = new Alarm();
alarmTemp.setId(documentSnapshot.getId());
alarmTemp.setTest(documentSnapshot.get("test").toString());
alarm.setValue(alarmTemp);
} else {
Log.d(TAG, "ERROR");
}
}
}
Thank you for reading, I'm looking forward to the answer(s)!
The reason you have to use both
model.getAlarmLiveData()
andmodel.getAlarm()
looks to be that your AlarmLiveData class extends LiveData but sets a value for the contained MutableLiveData member variable instead of setting its own class value.Inside your AlarmLiveData class:
I'm not sure why you're creating a DAO class and I would most likely move that code directly into the AlarmViewModel class. But, here is how you can alter your current DAO class if you don't want to remove it:
Your AlarmViewModel class would look something like this:
Finally, in your Activity: