如何使用RxJava和Realm构建本地数据源



Realm现在支持RxJava 2,它引入了asFlowable功能,我对此感到非常兴奋,所以感谢所有为此做出贡献的人。

我面临的问题是如何最好地管理本地数据源singleton类中领域实例的生命周期。我的本地数据源类似于这里的Android架构示例。在RxJava的Realm示例中,他们在onCreate中实例化一个领域实例,并在活动的onDestroy中关闭它。但是,由于我的本地数据源是一个单例,所以我没有这些生命周期事件来实例化和关闭实例。

问题是:我应该在每次创建单例时实例化一个领域实例,并仅在单例被销毁时关闭它,还是应该在活动/片段中实例化一个王国实例,将其注入本地数据源,然后在活动/碎片中关闭它?欢迎任何其他建议。谢谢

他们在onCreate中实例化一个领域实例,并在活动的onDestroy中关闭它

这是针对UI线程Realm的。

将其注入本地数据源

您收到的Realm实例是线程本地引用计数实例,而不是"线程安全"的单例。因此,您可能不应该直接注入Realm,因为它将被限制在一个给定的线程中。


通常,UI线程Realm可以由ViewModelretained fragmentonCreate()/onDestroy()等管理,因为Realm只有在RealmResults有效的情况下才提供通知,这意味着Realm实例是打开的。

因此,要在任何线程上公开RealmResults,不知道它是RealmResult这一事实,您需要进行

public Flowable<List<ChatsModel>> getAllChatsData(Realm realm) {
RealmQuery<ChatsModel> query = realm.where(ChatsModel.class);
if(realm.isAutoRefresh()) {
return query.findAllAsync().asFlowable().filter(RealmResults::isLoaded);
} else {
return Flowable.just(query.findAll());
} 
}

正如您所看到的,这将接收Realm实例作为其输入。现在,如果你想删除这个参数,你需要在本地数据源中隐藏引用计数,我个人认为LiveData是最好的选择,因为它有onActive()/onInactive()回调。

public class RealmLiveData<T extends RealmModel> extends MutableLiveData<List<T>> {
public interface QueryDefinition<M extends RealmModel> {
RealmResults<M> createResults(Realm realm);
}
private final QueryDefinition<T> queryDefinition;
public RealmLiveData(QueryDefinition<T> query) {
this.queryDefinition = query;
// TODO: handle realm config other than DefaultConfig if needed
}
Realm realm;
RealmResults<T> results;
RealmChangeListener<RealmResults<T>> realmChangeListener = new RealmChangeListener<RealmResults<T>>() {
@Override
public void onChange(RealmResults<T> results) {
if(results.isLoaded()) {
setValue(results);
}
}
}
@Override
public void onActive() {
realm = Realm.getDefaultInstance();
results = queryDefinition.createResults(realm);
results.addChangeListener(realmChangeListener);
}
@Override
public void onInactive() {
setValue(Collections.emptyList());
results.removeChangeListener(realmChangeListener);
realm.close();
realm = null;
}
}

然后你可以暴露一个LiveData:

public class MyDao {
public LiveData<List<MyObject>> findMyObjectsWithChanges() {
return new RealmLiveData<MyObject>(new QueryDefinition<MyObject>() {
@Override
public RealmResults<MyObject> createResults(Realm realm) {
return realm.where(MyObject).findAllAsync();
}
});
}
}

Lambda表达式使变得更好

public class MyDao {
public LiveData<List<MyObject>> findMyObjectsWithChanges() {
return new RealmLiveData<MyObject>((realm) -> realm.where(MyObject.class).findAllAsync());
}
}

所以这是一个值得研究的可能性。

注意,不关闭UI线程上的Realm文件并不一定危险,因为它会自动更新。唯一的缺点是你不能再使用要求文件完全关闭的功能,比如删除它

就我个人而言,我认为生命周期事件确实属于模型层,因为你经常需要它们来做其他事情,比如控制传感器和/或GPS。

特别是现在架构组件已经达到1.0,我建议将LifecycleObservable作为控制Realm实例的手段:https://developer.android.com/topic/libraries/architecture/lifecycle.html

最新更新