[英]ViewModel manipulation in MVVM Architecture
我的問題是,我需要先對會議室數據庫中的數據進行預處理,然后才能在視圖中顯示它。
因此,這里是我的應用程序的一些上下文:
我正在編寫“記錄卡” android應用程序。 因此,我有一個房間數據庫,其中存儲了我所有的記錄卡。 實體中的信息是:
@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)
我在實體周圍有正常的房間設置,我在一些教程中找到了它們,包括: Dao, Database, Repository
。 此外,我有一個ViewModel
連接到Repository
。 還有一個用於顯示當前Question的View
連接到ViewModel
。
我的點子:
我的想法是, ViewModel
可以保存所有需要的Cards的LiveData
(例如,帶有特定的Topic)。 我需要一些關於該數據的算法,它將選擇我需要View
下一張卡片。 這取決於:多少張卡具有不同的箱號,哪些卡是最近的10個問題,等等。
我的問題:
在我的ViewModel
我從repository
接收LiveData
。 每個教程僅顯示帶有視圖的Room-Database數據。 但是我需要在ViewModel
內部做一些預處理。 使用.getValue()
訪問LiveData
不起作用,僅返回null
對象。 在ViewModel
觀察數據也不起作用,因為為此您需要一個Activity
。
我不知道該將算法與數據庫中的數據一起放置在哪里。 我不想將其放在View
因為我想在ViewModel
保存當前算法參數。
一些代碼可以更好地理解我的程序:
@道
@Query("SELECT * FROM Karteikarte WHERE BoxnummerMixed = :Boxnummer")
LiveData<List<Karteikarte>> getKarteikartenInBoxMixed(int Boxnummer);
@Query("SELECT * FROM Karteikarte WHERE BoxnummerTopic = :Boxnummer AND Thema = :thema")
LiveData<List<Karteikarte>> getKarteikartenInBoxTopic(int Boxnummer, int thema);
資料庫
public LiveData<List<Karteikarte>> getKarteikarteInBoxMixed(int boxnummer){
return karteikarteDao.getKarteikartenInBoxMixed(boxnummer);
}
public LiveData<List<Karteikarte>> getKarteikarteInBoxTopic(Thema thema, int boxnummer){
return karteikarteDao.getKarteikartenInBoxTopic(thema.ordinal(), boxnummer);
}
視圖模型
public LearningViewModel(Application application){
super(application);
repository = new KarteikarteRepository(application);
}
//This method will be called from the View at onCreate
public void initLearning(){
allCards = repository.getKarteikarteInBoxMixed(1);
}
//This method will be called from the View
public Karteikarte nextCard() {
// here will be a more complex algorithm
Random random = new Random();
List<Karteikarte> list = allCards.getValue();
return list.get(random.nextInt(list.size()));
}
您可以在進入Fragment或Activity之前使用Transformations修改viewModel / Repository中的數據
Transforamtions.map創建一個新的LiveData,它將觀察您傳遞的liveData以及何時有新數據,該數據將通過您提供的函數傳遞,然后再將其發送到Fragment或Activity
private val liveDataFromRoomDatabase: LiveData<RecordCard> = getFromRoomDatabase()
val recordCardLiveData:LiveData<RecordCard>
= Transformations.map(liveDataFromRoomDatabase){ recordCard ->
// do all the changes you need here and return record card in this function
recordCard
}
對於更復雜的用例,可以使用MediatorLiveData
在這里,我使用了Transformations.switchMap()和Transformations.map()
要了解轉換和MediatorLiveData的詳細信息,您可以觀看Android Dev Summit '18的視頻-LiveData的樂趣
private MutableLiveData<Integer> boxNumberLiveData = new MutableLiveData<>();
private final LiveData<List<Karteikarte>> allCardsLiveData;
//Observe this from Fragment or Activity
public final LiveData<Karteikarte> karteikarteLiveData;
LearningViewModel(){
// when ever you change box number below function is called and list of Karteikarte will be updated
allCardsLiveData = Transformations.switchMap(boxNumberLiveData, new Function<Integer, LiveData<List<Karteikarte>>>() {
@Override
public LiveData<List<Karteikarte>> apply(Integer number) {
if(number == null)return null;
return repository.getKarteikarteInBoxMixed(1);
}
});
// when ever list of Karteikarte is changed, below function will be called and a random Karteikarte will be selected
karteikarteLiveData = Transformations.map(allCardsLiveData, new Function<List<Karteikarte>, Karteikarte>() {
@Override
public Karteikarte apply(List<Karteikarte> list) {
return getRandomKarteikarte(list);
}
});
}
public void initLearning(){
//Enter box number here
// you can modify box number anytime you want, everything will change respectively
boxNumberLiveData.setValue(1);
}
private Karteikarte getRandomKarteikarte(@Nullable List<Karteikarte> list){
if(list == null)return null;
Random random = new Random();
return list.get(random.nextInt(list.size()));
}
如果您想獲得下一個隨機的Karteikarte。 最好的實現方法是在數據庫中有一個額外的字段。
@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)
- isShown(boolean)
在查詢數據時,需要添加isShown is false
額外條件,因此當您要加載下一個Karteikarte時,只需將當前Karteikarte的isShown字段更新為true
如果要重新使用已顯示的Karteikarte,則可以在開始過程時將isShown值重置為false
對於實時數據,您需要使用LifeCycleOwner(您需要在該活動或存儲庫或vm中實施)。檢查google中的示例代碼以獲取實時數據
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.