使用领域和 LiveData。将 LiveData<RealmResults<CustomModelObject>> 转换为 LiveData<List<CustomModelObject>>
Using Realm and LiveData. Converting LiveData<RealmResults<CustomModelObject>> to LiveData<List<CustomModelObject>>
我正在试用 Realm 以及 Android 架构组件,包括 LiveData。
我一直在关注 Google 的应用程序架构指南:
https://developer.android.com/topic/libraries/architecture/guide.html
...将 Room 替换为 Realm。
我的一切都在使用:
LiveData<RealmResults<CustomModelObject>>
从我的存储库层直接通过 ViewModel 到 View。
我认为从存储库返回更多通用类型可能会更好,因此 LiveData<List<CustomModelObject>>
而不是 LiveData<RealmResults<CustomModelObject>>
。
这是我遇到问题的代码片段:
@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()
当前 returns LiveData<RealmResults<Inspiration>>
.
我想将其转换为LiveData<List<Inspiration>>
。
我尝试了各种 Transformations.map
和 Transformations.switchMap
等等,但都没有成功,我想我现在已经盯着它看太久了:)
我是在正确的道路上还是遗漏了一些明显的东西?
非常感谢任何帮助。
谢谢,
保罗.
更新
DAO:
public RealmLiveData<CustomModelObject> getCustomModelObjects() {
return asLiveData(realm.where(CustomModelObject.class).findAllAsync());
}
asLiveData 实现:
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<RealmResults<T>
替换为 LiveData<List<T>>
就足以解决您的问题。
不过,我建议您尝试 RealmLiveResults
class 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()
应该可以工作。
如果你需要:
val list : LiveData<List<mRealmObject>>
首先:创建这个文件:
class RealmLiveData<T : RealmModel>(private val results: RealmResults<T>) :
LiveData<RealmResults<T>>() {
private val listener: RealmChangeListener<RealmResults<T>> =
RealmChangeListener { results -> value = results }
override fun onActive() {
results.addChangeListener(listener)
}
override fun onInactive() {
results.removeChangeListener(listener)
}
}
fun <T: RealmModel> RealmResults<T>.asLiveData() = RealmLiveData<T>(this)
第二:获取新的 RealmLiveData :
val mRealmLiveData = realm.where(mRealmObject::class.java).findAllAsync().asLiveData()
最后,像这样获取您需要的列表:
val list: LiveData<List<mRealmObject>> = Transformations.map(mRealmLiveData) {
realmResult ->
realm.copyFromRealm(realmResult)
}
如果在 ViewModel 中使用它:
//get realm instance
val realm: Realm by lazy {
Realm.getDefaultInstance()
}
// get your live data
val list: LiveData<List<mRealmObject>> = Transformations.map(mRealmLiveData) {
realmResult ->
realm.copyFromRealm(realmResult)
}
// Close your realm instance onCleraded
override fun onCleared() {
realm.close()
super.onCleared()
}
我正在试用 Realm 以及 Android 架构组件,包括 LiveData。
我一直在关注 Google 的应用程序架构指南:
https://developer.android.com/topic/libraries/architecture/guide.html
...将 Room 替换为 Realm。
我的一切都在使用:
LiveData<RealmResults<CustomModelObject>>
从我的存储库层直接通过 ViewModel 到 View。
我认为从存储库返回更多通用类型可能会更好,因此 LiveData<List<CustomModelObject>>
而不是 LiveData<RealmResults<CustomModelObject>>
。
这是我遇到问题的代码片段:
@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()
当前 returns LiveData<RealmResults<Inspiration>>
.
我想将其转换为LiveData<List<Inspiration>>
。
我尝试了各种 Transformations.map
和 Transformations.switchMap
等等,但都没有成功,我想我现在已经盯着它看太久了:)
我是在正确的道路上还是遗漏了一些明显的东西?
非常感谢任何帮助。
谢谢, 保罗.
更新
DAO:
public RealmLiveData<CustomModelObject> getCustomModelObjects() {
return asLiveData(realm.where(CustomModelObject.class).findAllAsync());
}
asLiveData 实现:
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<RealmResults<T>
替换为 LiveData<List<T>>
就足以解决您的问题。
不过,我建议您尝试 RealmLiveResults
class 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()
应该可以工作。
如果你需要:
val list : LiveData<List<mRealmObject>>
首先:创建这个文件:
class RealmLiveData<T : RealmModel>(private val results: RealmResults<T>) :
LiveData<RealmResults<T>>() {
private val listener: RealmChangeListener<RealmResults<T>> =
RealmChangeListener { results -> value = results }
override fun onActive() {
results.addChangeListener(listener)
}
override fun onInactive() {
results.removeChangeListener(listener)
}
}
fun <T: RealmModel> RealmResults<T>.asLiveData() = RealmLiveData<T>(this)
第二:获取新的 RealmLiveData :
val mRealmLiveData = realm.where(mRealmObject::class.java).findAllAsync().asLiveData()
最后,像这样获取您需要的列表:
val list: LiveData<List<mRealmObject>> = Transformations.map(mRealmLiveData) {
realmResult ->
realm.copyFromRealm(realmResult)
}
如果在 ViewModel 中使用它:
//get realm instance
val realm: Realm by lazy {
Realm.getDefaultInstance()
}
// get your live data
val list: LiveData<List<mRealmObject>> = Transformations.map(mRealmLiveData) {
realmResult ->
realm.copyFromRealm(realmResult)
}
// Close your realm instance onCleraded
override fun onCleared() {
realm.close()
super.onCleared()
}