RxJava 2并在IO线程上使用Realm

时间:2017-01-20 09:00:03

标签: caching realm repository-pattern rx-java2

我在DataManager中创建一个方法,首先从缓存中下载数据,然后从服务器API请求数据,保存结果并将网络数据发送给演示者(在MVP中)。

问题是,当我想在后台进行操作时,使用Realm会在UI线程上进行。我发现了一些关于第一个RxJava的域支持的文章,但我们正在使用另一个具有另一个API的版本,所以这些Realm方法对我们没有帮助(toObservable())。

如何解决问题?

此外,正如我所看到的,所有其他方法都在IO线程上处理,只有Realm在Ui上工作,无论我放置subscribeOn(Schedulers.io())的事实。为什么会这样?

@Override
public Observable<ChatsRepoAnswerModel> getChats() {
    return getChatsFromCache(STATUS_OK)
            .subscribeOn(Schedulers.io())
            .mergeWith(
                    getChatsService()
                            .getChats()
                            .subscribeOn(Schedulers.io())
                            .map(ChatResponseModel::getResult)
                            .flatMap(mChatsMapper::transformAll)
                            .doOnNext(this::saveChats)
                            .doOnNext(Collections::sort)                            
                            .onErrorResumeNext(getChatsFromCache(STATUS_ERROR))                               
            .observeOn(AndroidSchedulers.mainThread());
}


private void saveChats(List<ChatDataModel> realmObjects) {        
    Realm.getDefaultInstance().executeTransaction(realm -> {
        realm.insertOrUpdate(realmObjects);
    });
}

private Observable<ChatsRepoAnswerModel> getChatsFromCache(int aStatus) {
    Realm realm = Realm.getDefaultInstance();
    RealmResults<ChatDataModel> chats = realm.where(ChatDataModel.class).findAll();
    return processChatResponse(realm.copyFromRealm(chats), aStatus);
}

1 个答案:

答案 0 :(得分:1)

我认为这完全无视Realm试图给你的零拷贝设计:

  • 来自Realm以RealmResults形式提供的自动更新被动数据集的单向数据流(意味着您会在数据时收到通知设置更改)
  • 延迟评估,只读取一次访问的元素,RealmResults只是一个“光标”,RealmObject仅在调用访问者时读取数据< / LI>
  • 一致性:所有托管的RealmProxies指向同一个对象,因此您在任何地方都没有“过时”数据(除了保留的非自动更新后台线程之外,这是通常是用户错误)

这很有趣,因为realm.copyFromRealm()创建了非托管对象,通常没有这些属性:

  • 不再自动更新
  • 急切地评估整个数据集并将所有数据复制到字段
  • 因此,在所有使用过的地方都不一定是最新的

无论如何,在后台线程上创建分离的RealmObjects的解决方案是在该线程上打开实例,复制数据集,然后关闭实例。

Observable.fromCallable(() -> { // <-- defer to whatever thread you're running it on
        try(Realm realm = Realm.getDefaultInstance()) {
            return realm.copyFromRealm(realm.where(Cat.class).findAll());
        } // <-- auto-close
    })
.subscribeOn(Schedulers.whatever());

通常,按照预期使用Realm更容易,尤其是对于更大的数据集。