在使用架构组件的Android应用中,我有以下视图模型:
以上的
我该如何实现呢?我应该扩展MutableLiveData还是使用MediatorLiveData或者使用Transformations.switchMap()呢?
更新:
明天我会尝试以下操作(今晚太晚了)-
Dao方法我将更改为返回列表而不是LiveData:
public class MainViewModel extends AndroidViewModel {
private final MutableLiveData<List<String>> mUnchecked = new MutableLiveData<>();
private LiveData<List<String>> mChecked;
public void setUnchecked(List<String> list) {
mUnchecked.setValue(list);
}
public LiveData<List<String>> getChecked() { // OBSERVED BY A FRAGMENT
return mChecked;
}
public MainViewModel(Application app) {
super(app);
mChecked = Transformations.switchMap(mUnchecked,
list-> myDao().checkWords(list));
}
以上的
switchMap
的目的是检查作为字符串列表传递的单词中,哪些存在于Room表中:@Dao
public interface MyDao {
@Query("SELECT word FROM dictionary WHERE word IN (:words)")
LiveData<List<String>> checkWords(List<String> words);
以上代码对我很有效!
但是我想要的略有不同 -
我希望传递一个字符串 (单词) -> 整数 (分数) 的映射表,而不是字符串列表:
public void setUnchecked(Map<String,Integer> map) {
mUnchecked.setValue(map);
}
这些整数将作为我的游戏的单词分数。一旦checkWords()
返回结果,我希望将那些在Room表中找不到的单词得分设置为null
,而将其他单词的得分保留。
编程代码很简单(通过遍历mChecked.getValue()
并将在DAO方法返回的列表中找不到的单词设置为null
)- 但如何“与我的LiveData
成员配合”?
TL;DR
我想要更改我的视图模型以持有映射而不是列表:
public class MainViewModel extends AndroidViewModel {
private final MutableLiveData<Map<String,Integer>> mUnchecked = new MutableLiveData<>();
private final MutableLiveData<Map<String,Integer>> mChecked = new MutableLiveData<>();
public void setUnchecked(Map<String,Integer> map) {
mUnchecked.setValue(map);
}
public LiveData<Map<String,Integer>> getChecked() { // OBSERVED BY A FRAGMENT
return mChecked;
}
public MainViewModel(Application app) {
super(app);
// HOW TO OBSERVE mUnchecked
// AND RUN myDao().checkWords(new ArrayList<>(mUnchecked.getValue().keys()))
// WRAPPED IN Executors.newSingleThreadScheduledExecutor().execute( ... )
// AND THEN CALL mChecked.postValue() ?
}
我该如何实现呢?我应该扩展MutableLiveData还是使用MediatorLiveData或者使用Transformations.switchMap()呢?
更新:
明天我会尝试以下操作(今晚太晚了)-
Dao方法我将更改为返回列表而不是LiveData:
@Query("SELECT word FROM dictionary WHERE word IN (:words)")
List<String> checkWords(List<String> words);
然后我将尝试扩展 MutableLiveData
:
private final MutableLiveData<Map<String,Integer>> mChecked = new MutableLiveData<>();
private final MutableLiveData<Map<String,Integer>> mUnchecked = new MutableLiveData<Map<String,Integer>>() {
@Override
public void setValue(Map<String,Integer> uncheckedMap) {
super.setValue(uncheckedMap);
Executors.newSingleThreadScheduledExecutor().execute(() -> {
List<String> uncheckedList = new ArrayList<>(uncheckedMap.keySet());
List<String> checkedList = WordsDatabase.getInstance(mApp).wordsDao().checkWords(uncheckedList);
Map<String,Integer> checkedMap = new HashMap<>();
for (String word: uncheckedList) {
Integer score = (checkedList.contains(word) ? uncheckedMap.get(word) : null);
checkedMap.put(word, score);
}
mChecked.postValue(checkedMap);
});
}
};
Map<String, Integer>
的键是单词吗?如果是这样,那么虽然我理解你想要将未被checkWords()
返回的单词的Integer
替换为null
,但是对于那些被checkWords()
返回的单词,你想要发生什么呢?你会保留Integer
吗?还是计算一个新值,只是碰巧不是null
? - CommonsWarenull
替换无效单词的分数,并保留其他分数不变。我正在考虑扩展MutableLiveData
,不确定是否正确(请参见更新的问题)。 - Alexander Farber