Android MVVM体系结构中的视图模型操作
我的问题是,我需要在视图中显示房间数据库中的数据之前对其进行预处理 因此,这里是我的应用程序的一些上下文: 我正在编写一个“记录卡”android应用程序。因此,我有一个房间数据库,所有的记录卡都存储在那里。实体中的信息为: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) 我在几个教程中找到了关于实体的常规文件室设置,其中包括
@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)