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