簡體   English   中英

MVVM體系結構中的ViewModel操作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM