Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android MVVM体系结构中的视图模型操作_Android_Mvvm_Viewmodel_Android Room - Fatal编程技术网

Android MVVM体系结构中的视图模型操作

Android MVVM体系结构中的视图模型操作,android,mvvm,viewmodel,android-room,Android,Mvvm,Viewmodel,Android Room,我的问题是,我需要在视图中显示房间数据库中的数据之前对其进行预处理 因此,这里是我的应用程序的一些上下文: 我正在编写一个“记录卡”android应用程序。因此,我有一个房间数据库,所有的记录卡都存储在那里。实体中的信息为: @Entitiy: - ID - Question - Answer - Topic - Boxnumber (Box depends on how often i was right with my Answer) 我在几个教程中找到了关于实体的常规文件室设置,其中包括

我的问题是,我需要在视图中显示房间数据库中的数据之前对其进行预处理

因此,这里是我的应用程序的一些上下文:

我正在编写一个“记录卡”android应用程序。因此,我有一个房间数据库,所有的记录卡都存储在那里。实体中的信息为:

@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)
我在几个教程中找到了关于实体的常规文件室设置,其中包括:
Dao、数据库、存储库
。此外,我还有一个连接到
存储库的
ViewModel
。以及一个
视图
,用于显示连接到
视图模型
的当前问题

我的想法:

我的想法是,
ViewModel
可以保存所有需要的卡片的
LiveData
(例如,有一个特定的主题)。 我需要对该数据进行一些算法,以便为
视图选择我需要的下一张卡。这取决于:有多少卡片有不同的箱号,最后10个问题是哪张卡片,等等

我的问题:

在我的
视图模型中
我从
存储库
接收
实时数据
。每个教程仅显示带有视图的房间数据库数据。但是我需要在
ViewModel
中进行一些预处理。使用
.getValue()
访问
LiveData
不起作用,只返回
null
对象。观察
ViewModel
中的数据也不起作用,因为您需要一个
活动

我不知道应该把处理数据库数据的算法放在哪里。我不想把它放在
视图中,因为我想把当前算法参数保存在
视图模型中

一些代码可以更好地理解我的程序:

@刀

@Query(“从Karteikart中选择*,其中BoxnummerMixed=:Boxnummer”)
LiveData getKarteikartenInBoxMixed(int-Boxnummer);
@查询(“从Karteikart中选择*,其中BoxnummerTopic=:Boxnummer和Thema=:Thema”)
LiveData 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 LiveData getkartikarnboxmixed(int-boxnumer){
返回Karteikartdao.getKarteikertenboxMixed(boxnummer);
}
公共实时数据getKarteikarteInBoxTopic(Thema Thema,int-boxnummer){
返回kartikartedao.getkartikartenInboxTopic(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()));
}
公共学习视图模型(应用程序){
超级(应用);
存储库=新的KarteikarteRepository(应用程序);
}
//此方法将在onCreate时从视图中调用
公共学习{
allCards=repository.getkarteinboxmixed(1);
}
//将从视图中调用此方法
公共卡丁车nextCard(){
//下面是一个更复杂的算法
随机=新随机();
List List=allCards.getValue();
return list.get(random.nextInt(list.size());
}

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

在转到片段或活动之前,您可以使用该示例代码修改viewModel/repository中的数据

Transforamtions.map创建一个新的LiveData,它将观察您传递的LiveData,当有新数据时,数据将通过您提供的函数传递,然后再发送到片段或活动

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
}
private val liveDataFromRoomDatabase:LiveData=getFromRoomDatabase()
val recordCardLiveData:LiveData
=Transformations.map(liveDataFromRoomDatabase){recordCard->
//在此处执行所有需要的更改,并在此函数中返回记录卡
记录卡
}

对于更复杂的用例,您可以使用这里我使用的和

要了解转换和MediaLiveData的详细信息,您可以从2018年Android开发峰会观看此视频

在查询数据时,您需要添加额外的条件,
isShown为false
因此,当您想要加载下一个Karteikart时,只需将当前Karteikart的isShown字段更新为true


如果您想重新使用已经显示的Karteikart,您只需在启动流程时将isShown值重置为false即可

您已经在使用
ViewModel
内部
存储库
,那么为什么要在
ViewModel
中使用
LiveData
?您可以直接在
ViewModel
中从
Repository
查询您的列表。教程显示存储库只传递它从Dao获得的LiveData。存储库中的方法调用Dao中的方法,从Dao接收LiveData并将该LiveData传递给ViewModel。还有别的办法吗?!我在文章中添加了一些代码,以便更好地理解视图模型的外观。我读到视图模型不应该是生命周期所有者:视图模型不是生命周期所有者。活动或片段可能是生命周期所有者。感谢您的帮助。这对第一张卡很有效。但是有没有办法从我的角度触发第二张卡的“GetRandomKarteikart”?
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
}
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()));
}
@Entitiy:
- ID
- Question
- Answer
- Topic
- Boxnumber (Box depends on how often i was right with my Answer)
- isShown(boolean)