使用领域和LiveData.转换LiveData< RealmResults< CustomModelObject>>到LiveData< List< CustomModelObject>>. [英] Using Realm and LiveData. Converting LiveData<RealmResults<CustomModelObject>> to LiveData<List<CustomModelObject>>
问题描述
我正在尝试将Realm与包括LiveData在内的Android体系结构组件一起使用.
I am trying out Realm along with Android architecture components including LiveData.
我一直在关注Google的《应用程序体系结构指南》:
I have been following Google's Guide to Application Architecture:
https://developer.android.com/topic/libraries/architecture/guide.html
...用领域代替Room.
...substituting Room with Realm.
我正在使用的所有工具都可以使用:
I have everything working using:
LiveData<RealmResults<CustomModelObject>>
从我的存储库层
一直到ViewModel到View.
from my repository layer right through ViewModel to View.
我认为只从存储库中返回更多泛型类型可能更好,所以LiveData<List<CustomModelObject>>
而不是LiveData<RealmResults<CustomModelObject>>
.
I am thinking it might be nicer to only have more generic types coming back from repository so LiveData<List<CustomModelObject>>
rather than LiveData<RealmResults<CustomModelObject>>
.
这是我遇到问题的代码段:
Here is a code snippet of where I have got stuck:
@NonNull
@Override
protected LiveData<List<CustomModelObject>> loadFromDb() {
return Transformations.switchMap(customModelObjectsDao.getCustomModelObjects(),
new Function<RealmResults<CustomModelObject>, LiveData<List<CustomModelObject>>>() {
@Override
public LiveData<List<CustomModelObject>> apply(RealmResults<CustomModelObject> data) {
if (data == null) {
return AbsentLiveData.create();
} else {
return customModelObjectsDao.getCustomModelObjects();
}
}
});
}
customModelObjectsDao.getCustomModelObjects()
当前返回LiveData<RealmResults<Inspiration>>
.
我想将其转换为LiveData<List<Inspiration>>
.
我尝试过各种Transformations.map
和Transformations.switchMap
等都没有成功,我想我已经盯着它太久了:)
I have tried various Transformations.map
and Transformations.switchMap
etc with no success and I think I have been staring at it too long now :)
我是在正确的道路上还是我错过了明显的东西?
Am I on the right path or am I missing something obvious?
非常感谢您的帮助.
谢谢, 保罗.
更新
DAO:
public RealmLiveData<CustomModelObject> getCustomModelObjects() {
return asLiveData(realm.where(CustomModelObject.class).findAllAsync());
}
asLiveData Impl:
asLiveData Impl:
fun <T: RealmModel> RealmResults<T>.asLiveData() = RealmLiveData<T>(this)
fun Realm.CustomModelObjectsDao(): CustomModelObjectsDao = CustomModelObjectsDao(this)
更新2
public class RealmLiveData<T> extends LiveData<RealmResults<T>> {
private RealmResults<T> results;
private final RealmChangeListener<RealmResults<T>> listener = new RealmChangeListener<RealmResults<T>>() {
@Override
public void onChange(RealmResults<T> results) {
setValue(results);
}
};
public RealmLiveData(RealmResults<T> realmResults) {
results = realmResults;
}
@Override
protected void onActive() {
results.addChangeListener(listener);
}
@Override
protected void onInactive() {
results.removeChangeListener(listener);
}
}
推荐答案
在您的情况下,用LiveData<List<T>>
替换LiveData<RealmResults<T>
就足以解决您的问题.
In your case, replacing LiveData<RealmResults<T>
with LiveData<List<T>>
would be enough to solve your problem.
但是,我建议尝试使用
However, I'd advise trying out the RealmLiveResults
class that is available in the official example:
/**
* This class represents a RealmResults wrapped inside a LiveData.
*
* Realm will always keep the RealmResults up-to-date whenever a change occurs on any thread,
* and when that happens, the observer will be notified.
*
* The RealmResults will be observed until it is invalidated - meaning all local Realm instances on this thread are closed.
*
* @param <T> the type of the RealmModel
*/
public class LiveRealmResults<T extends RealmModel> extends LiveData<List<T>> {
private final RealmResults<T> results;
// The listener will notify the observers whenever a change occurs.
// The results are modified in change. This could be expanded to also return the change set in a pair.
private OrderedRealmCollectionChangeListener<RealmResults<T>> listener = new OrderedRealmCollectionChangeListener<RealmResults<T>>() {
@Override
public void onChange(@NonNull RealmResults<T> results, @Nullable OrderedCollectionChangeSet changeSet) {
LiveRealmResults.this.setValue(results);
}
};
@MainThread
public LiveRealmResults(@NonNull RealmResults<T> results) {
//noinspection ConstantConditions
if (results == null) {
throw new IllegalArgumentException("Results cannot be null!");
}
if (!results.isValid()) {
throw new IllegalArgumentException("The provided RealmResults is no longer valid, the Realm instance it belongs to is closed. It can no longer be observed for changes.");
}
this.results = results;
if (results.isLoaded()) {
// we should not notify observers when results aren't ready yet (async query).
// however, synchronous query should be set explicitly.
setValue(results);
}
}
// We should start observing and stop observing, depending on whether we have observers.
/**
* Starts observing the RealmResults, if it is still valid.
*/
@Override
protected void onActive() {
super.onActive();
if (results.isValid()) { // invalidated results can no longer be observed.
results.addChangeListener(listener);
}
}
/**
* Stops observing the RealmResults.
*/
@Override
protected void onInactive() {
super.onInactive();
if (results.isValid()) {
results.removeChangeListener(listener);
}
}
}
这样,您的dao
可以公开LiveData<List<T>>
,而您的Transformations.map()
应该可以工作.
This way your dao
can expose LiveData<List<T>>
, and your Transformations.map()
should work.
这篇关于使用领域和LiveData.转换LiveData< RealmResults< CustomModelObject>>到LiveData< List< CustomModelObject>>.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!