简体   繁体   English

MVVM体系结构中的ViewModel操作

[英]ViewModel manipulation in MVVM Architecture

My Problem is, that i need to preprocess data from the Room Database before showing it in my View. 我的问题是,我需要先对会议室数据库中的数据进行预处理,然后才能在视图中显示它。

Therefore here some Context of my Application: 因此,这里是我的应用程序的一些上下文:

Im programming a "record card" android application. 我正在编写“记录卡” android应用程序。 Therefore i have a Room Database where all my record-cards are stored. 因此,我有一个房间数据库,其中存储了我所有的记录卡。 The Information in the Entitiy is: 实体中的信息是:

@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)

Around the Entity i have the normal Room Setup, i found in several tutorials, with: Dao, Database, Repository . 我在实体周围有正常的房间设置,我在一些教程中找到了它们,包括: Dao, Database, Repository Furthermore i have a ViewModel connected to the Repository . 此外,我有一个ViewModel连接到Repository And a View for showing the current Question connected to the ViewModel . 还有一个用于显示当前Question的View连接到ViewModel

My Idea: 我的点子:

My Idea was that the ViewModel can hold LiveData of all needed Cards (with a specific Topic for example). 我的想法是, ViewModel可以保存所有需要的Cards的LiveData (例如,带有特定的Topic)。 I need some algorithm on that data which will select me my next Card i need for the View . 我需要一些关于该数据的算法,它将选择我需要View下一张卡片。 This depends on: How much cards have different boxnumbers, which cards was the last 10 Questions, etc. 这取决于:多少张卡具有不同的箱号,哪些卡是最近的10个问题,等等。

My Problem: 我的问题:

In my ViewModel i recieve LiveData from the repository . 在我的ViewModel我从repository接收LiveData Every Tutorial shows only displaying the Room-Database Data with an View. 每个教程仅显示带有视图的Room-Database数据。 But i need to do some preprocessing inside the ViewModel . 但是我需要在ViewModel内部做一些预处理。 Accessing the LiveData with .getValue() is not working and only returning null objects. 使用.getValue()访问LiveData不起作用,仅返回null对象。 Observing the Data in the ViewModel is also not working, because you need an Activity for this. ViewModel观察数据也不起作用,因为为此您需要一个Activity

I don't know where i should place the algorithm working with the data from the database. 我不知道该将算法与数据库中的数据一起放置在哪里。 I don't want to put it in the View because i want to hold the current algorithm parameters inside the ViewModel . 我不想将其放在View因为我想在ViewModel保存当前算法参数。

Some Code to understand my Program better: 一些代码可以更好地理解我的程序:

@Dao @道

@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);

Repository 资料库

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);
}

ViewModel 视图模型

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()));
}

You can use Transformations to modify data in viewModel/Repository before going to Fragment or Activity 您可以在进入Fragment或Activity之前使用Transformations修改viewModel / Repository中的数据

Transforamtions.map creates a New LiveData which will observe the liveData that you pass and when ever there is new data, The data will be passed though the function you provide before sending it to the Fragment or activity 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
}

For more complex use cases you can use MediatorLiveData 对于更复杂的用例,可以使用MediatorLiveData

Here i have used Transformations.switchMap() and Transformations.map() 在这里,我使用了Transformations.switchMap()Transformations.map()

For detail understanding of Transformations and MediatorLiveData, you can watch this Video from Android Dev Summit '18 - Fun with LiveData 要了解转换和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()));
}

If you want to get the next random Karteikarte. 如果您想获得下一个随机的Karteikarte。 The best way to implement this is to have a extra field in database. 最好的实现方法是在数据库中有一个额外的字段。

@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)
- isShown(boolean)

while querying the data you need to add extra condition that isShown is false so when you want to load next Karteikarte, you just need to update the current Karteikarte's isShown field to true 在查询数据时,需要添加isShown is false额外条件,因此当您要加载下一个Karteikarte时,只需将当前Karteikarte的isShown字段更新为true

if you want to re-use already shown Karteikarte, you can just reset isShown values to false when you want start the process 如果要重新使用已显示的Karteikarte,则可以在开始过程时将isShown值重置为false

对于实时数据,您需要使用LifeCycleOwner(您需要在该活动或存储库或vm中实施)。检查google中的示例代码以获取实时数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Android MVVM 架构中显示来自 ViewModel 的对话框 - Show Dialog from ViewModel in Android MVVM Architecture 从 MVVM 架构中的 ViewModel 更改片段 - Change fragment from ViewModel in MVVM architecture 使用 MVVM 架构的 ViewModel 注入(内部视图) - ViewModel injection (inside View) with MVVM Architecture 在MVVM架构中从ViewModel添加片段 - Add fragment from ViewModel in MVVM architecture Android MVVM体系结构-ViewModel中的Android参考/导入 - Android MVVM architecture - Android references/imports in ViewModel Android MVVM + 数据绑定 + 架构组件(ViewModel 和 Room)示例 - Example of Android MVVM + Databinding + Architecture Components (ViewModel and Room) 使用架构组件 MVVM 进行身份验证,将令牌从 Repository 传递到 ViewModel - Authentication with Architecture Components MVVM, passing token from Repository to ViewModel mvvm 架构中视图和视图模型责任的混淆 - confusion for view's and viewmodel's responsibility in mvvm architecture ViewModel 中的不可观察模型对象是针对 Android 中的 MVVM 架构吗? - Is non-observable model object in the ViewModel against MVVM architecture in Android? 如何在Android的MVVM架构中将动作从View发送到ViewModel - How to send actions from View to ViewModel in MVVM architecture in Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM