Android Room:处理与 LiveData 的关系
Android Room: Handling Relations with LiveData
所以我有两个模型(表),WordGroups
和Words
,它们之间的关系是一对多的。
所以我的模型和 Dao
看起来像:
@Entity
public class WordGroup {
@PrimaryKey
private int id;
@Ignore
private List<Word> words;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Word> getWords() {
return words;
}
public void setWords(List<Word> words) {
this.words = words;
}
}
@Entity
public class Word {
@PrimaryKey
private int id;
@ForeignKey(entity = WordGroup.class, parentColumns = "id", childColumns = "wordGroupId")
private int wordGroupId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getWordGroupId() {
return wordGroupId;
}
public void setWordGroupId(int wordGroupId) {
this.wordGroupId = wordGroupId;
}
}
和
@Dao
public interface Dao {
@Query("select * from WordGroup where id = :id")
LiveData<WordGroup> selectWordGroupById(int id);
@Query("select * from WordGroup")
LiveData<List<WordGroup>> selectAllWordGroups();
@Query("select * from Word where wordGroupId = :wordGroupId")
LiveData<List<Word>> selectWordsByWordGroupId(int wordGroupId);
}
现在我有一个方法可以选择 WordGroup
并使用 Transformations
:
设置它的 Word
s
public LiveData<WordGroup> getWordGroupWithWords(int id) {
LiveData<WordGroup> wordGroupLiveData = dao.selectWordGroupById(id);
LiveData<WordGroup> wordGroupWithWordsLiveData = Transformations.switchMap(wordGroupLiveData, inputWordGroup -> {
LiveData<List<Word>> wordsLiveData = dao.selectWordsByWordGroupId(inputWordGroup.getId());
LiveData<WordGroup> outputWordGroupsLiveData = Transformations.map(wordsLiveData, inputWords -> {
inputWordGroup.setWords(inputWords);
return inputWordGroup;
});
return outputWordGroupsLiveData;
});
return wordGroupWithWordsLiveData;
}
现在我想编写一个方法来选择所有 WordGroup
,同时为每个 WordGroup
设置它们的 Word
。该方法的签名应该是这样的:
public LiveData<List<WordGroup>> getAllWordGroupsWithWords();
好吧,我尝试了更多,并在 MediatorLiveData
:
的帮助下想出了这个解决方案
public LiveData<List<WordGroup>> getAllWordGroupsWithWords() {
LiveData<List<WordGroup>> wordGroupsLiveData = dao.selectAllWordGroups();
LiveData<List<WordGroup>> outputWordGroups = Transformations.switchMap(wordGroupsLiveData, inputWordGroups -> {
MediatorLiveData<List<WordGroup>> wordGroupsMediatorLiveData = new MediatorLiveData<>();
for (WordGroup wordGroup : inputWordGroups) {
wordGroupsMediatorLiveData.addSource(dao.selectWordsByWordGroupId(wordGroup.getId()), words -> {
wordGroup.setWords(words);
wordGroupsMediatorLiveData.postValue(inputWordGroups);
});
}
return wordGroupsMediatorLiveData;
});
return outputWordGroups;
}
现在完全是我想要的方式,但是有一些大问题。
首先,如果您在 MediatorLiveData
上使用方法 setValue
,它会多次调用观察者,我可以通过使用 [=14 来减少它调用观察者的次数=]
其次即使你只改变一个词,它也会为每个wordGroup
再次调用观察者!
当然,它不是最优化的解决方案,但确实有效。我非常乐于接受建议和改进。
所以我有两个模型(表),WordGroups
和Words
,它们之间的关系是一对多的。
所以我的模型和 Dao
看起来像:
@Entity
public class WordGroup {
@PrimaryKey
private int id;
@Ignore
private List<Word> words;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Word> getWords() {
return words;
}
public void setWords(List<Word> words) {
this.words = words;
}
}
@Entity
public class Word {
@PrimaryKey
private int id;
@ForeignKey(entity = WordGroup.class, parentColumns = "id", childColumns = "wordGroupId")
private int wordGroupId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getWordGroupId() {
return wordGroupId;
}
public void setWordGroupId(int wordGroupId) {
this.wordGroupId = wordGroupId;
}
}
和
@Dao
public interface Dao {
@Query("select * from WordGroup where id = :id")
LiveData<WordGroup> selectWordGroupById(int id);
@Query("select * from WordGroup")
LiveData<List<WordGroup>> selectAllWordGroups();
@Query("select * from Word where wordGroupId = :wordGroupId")
LiveData<List<Word>> selectWordsByWordGroupId(int wordGroupId);
}
现在我有一个方法可以选择 WordGroup
并使用 Transformations
:
Word
s
public LiveData<WordGroup> getWordGroupWithWords(int id) {
LiveData<WordGroup> wordGroupLiveData = dao.selectWordGroupById(id);
LiveData<WordGroup> wordGroupWithWordsLiveData = Transformations.switchMap(wordGroupLiveData, inputWordGroup -> {
LiveData<List<Word>> wordsLiveData = dao.selectWordsByWordGroupId(inputWordGroup.getId());
LiveData<WordGroup> outputWordGroupsLiveData = Transformations.map(wordsLiveData, inputWords -> {
inputWordGroup.setWords(inputWords);
return inputWordGroup;
});
return outputWordGroupsLiveData;
});
return wordGroupWithWordsLiveData;
}
现在我想编写一个方法来选择所有 WordGroup
,同时为每个 WordGroup
设置它们的 Word
。该方法的签名应该是这样的:
public LiveData<List<WordGroup>> getAllWordGroupsWithWords();
好吧,我尝试了更多,并在 MediatorLiveData
:
public LiveData<List<WordGroup>> getAllWordGroupsWithWords() {
LiveData<List<WordGroup>> wordGroupsLiveData = dao.selectAllWordGroups();
LiveData<List<WordGroup>> outputWordGroups = Transformations.switchMap(wordGroupsLiveData, inputWordGroups -> {
MediatorLiveData<List<WordGroup>> wordGroupsMediatorLiveData = new MediatorLiveData<>();
for (WordGroup wordGroup : inputWordGroups) {
wordGroupsMediatorLiveData.addSource(dao.selectWordsByWordGroupId(wordGroup.getId()), words -> {
wordGroup.setWords(words);
wordGroupsMediatorLiveData.postValue(inputWordGroups);
});
}
return wordGroupsMediatorLiveData;
});
return outputWordGroups;
}
现在完全是我想要的方式,但是有一些大问题。
首先,如果您在
MediatorLiveData
上使用方法setValue
,它会多次调用观察者,我可以通过使用 [=14 来减少它调用观察者的次数=]其次即使你只改变一个词,它也会为每个
wordGroup
再次调用观察者!
当然,它不是最优化的解决方案,但确实有效。我非常乐于接受建议和改进。