java - 将查询参数传递给 Android 应用程序中的 LiveData/Viewmodel
问题描述
由于我是编写 Android 应用程序的新手,因此我遵循了有关如何使用 Android 架构组件和 Firebase 来实现 MVVM(使用 LiveData、ViewModel 等)的教程。
我遵循的教程可以在这里找到:
我现在只剩下我认为是 MVVM 的一个不错的实现,但我无法理解我应该如何将查询参数传递给它。现在我需要硬编码要检索的文档的 ID:
public class AlarmDAO {
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
public AlarmLiveData getFirestoreLiveData() {
DocumentReference documentReference = firebaseFirestore.collection(Collection.ALARMS.name).document("5RxJNuNyhDJlz49wpBkw");
return new AlarmLiveData(documentReference);
}
}
然后由扩展类调用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;
}
}
然后我在我的活动中观察到这些数据:
model.getAlarmLiveData().observe(this, Observable -> {});
model.getAlarm().observe(this, alarm -> {
if (alarm != null) {
alarmTextView.setText(alarm.getTest());
else {
Log.d(TAG, "Waiting for data");
}
});
我的问题是我没有看到查询特定警报的方法。例如model.getAlarm("someId")
. 我的印象是它应该在 DAO 和/或 ViewModel 中完成,但我不知道怎么做。我不明白的另一件事是为什么我需要同时观察model.getAlarmLiveData()
我model.getAlarm()
的活动,因为只使用一个是行不通的。这两个问题的答案很可能很简单,但到目前为止我还没有弄清楚。
为了完整起见:Alarm
除了两个字符串的 getter 和 setter 之外,该类什么都没有,并且AlarmLiveData
该类在下面。
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");
}
}
}
感谢阅读,期待答案!
解决方案
您必须同时使用两者的原因model.getAlarmLiveData()
似乎model.getAlarm()
是您的 AlarmLiveData 类扩展了 LiveData 但为包含的 MutableLiveData 成员变量设置了一个值,而不是设置其自己的类值。
在您的 AlarmLiveData 类中:
// Comment out/Remove your 'public MutableLiveData<alarm> alarm' member variable from the top.
// You're going to want to set the value of the AlarmLiveData class itself instead.
// ...
// Then inside of your onEvent callback
@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());
// Set the value for the AlarmLiveData class directly
setValue(alarmTemp);
} else {
Log.d(TAG, "ERROR");
}
}
我不确定您为什么要创建 DAO 类,我很可能会将该代码直接移动到 AlarmViewModel 类中。但是,如果您不想删除当前的 DAO 类,可以通过以下方式更改它:
// Pass in the document id you want to create a document reference for
public AlarmLiveData getFirestoreLiveData(String documentId) {
DocumentReference documentReference = firebaseFirestore.collection(Collection.ALARMS.name).document(documentId);
return new AlarmLiveData(documentReference);
}
您的 AlarmViewModel 类看起来像这样:
public class AlarmViewModel extends ViewModel {
private AlarmDAO DAO = new AlarmDAO();
private AlarmLiveData liveData = null;
// Make sure to take in the document id so you can create the corresponding LiveData
public LiveData<Alarm> getAlarmLiveData(String documentId) {
// Only create a new LiveData instance if the current one is null.
// This is helpful if you intend to use this as a Shared ViewModel.
if(liveData == null){
liveData = DAO.getFirestoreLiveData(documentId);
}
return liveData;
}
}
最后,在您的活动中:
// Pass in the document id and observe the ViewModel
model.getAlarmLiveData("MY_DOCUMENT_ID").observe(this, alarm -> {
if (alarm != null) {
alarmTextView.setText(alarm.getTest());
}else{
Log.d(TAG, "Waiting for data");
}
});
推荐阅读
- javascript - 在 Selenium 中打开测试页面
- php - 根据某些条件从数组中删除一些行
- python - 循环浏览网页
- go - Golang MySQL 驱动程序不允许使用 ProxySQL 更改数据库
- javascript - 从回调中重新初始化 Javascript 库
- javascript - 我收到错误:在 else 语句中查询已释放或丢失的连接
- java - 将 gradle 转换为 maven
- c++ - Qt TCP 套接字 - 写入超过 15 个字节
- python - 使用 Python 3 将 90 天添加到给定日期 - 我不断收到错误
- r - 在 flexmix 中拟合二项式混合物 - 我做错了什么?