【问题标题】:RxJava Observable never perform onCompletedRxJava Observable 从不执行 onCompleted
【发布时间】:2017-05-09 15:40:23
【问题描述】:

我使用RxJava 和Realm 来查询移动数据库。查询完成后,我需要通知我的视图以更新列表,但似乎flatMap 和doOnNext 有效,但它永远不会继续完成。我需要一个触发器才能知道它已经结束了。

Realm.getDefaultInstance().asObservable().flatMap((realm) ->
        realm.where(FileDoc.class).isNull("parent").isNotNull("updatedDate").findAllSortedAsync("name").asObservable()
                .flatMap((files) -> {
                    documents.get("root").clear();
                    documents.get("root").addAll(realm.copyFromRealm(files));
                    return realm.where(Folder.class).isNull("parent").findAllSortedAsync("name").asObservable().doOnCompleted(() -> {
                        Log.e(TAG, "Barr!");
                    });
                })
                .doOnNext((folders) -> {
                    documents.get("root").addAll(realm.copyFromRealm(folders));
                })).doOnCompleted(() -> Log.e(TAG, "Fooo!"))
        .doOnError(error -> handleErrorEvent(error))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(AndroidSchedulers.from(backgroundLooper))
        .subscribe();

这里的Barr! 和Fooo! 从来没有打印出来……有人知道吗?


更新

Realm.getDefaultInstance().asObservable().first().flatMap((realm) ->
                realm.where(IncidentTemplate.class).equalTo("deleted", false).findAllAsync().asObservable()
                        .filter(results -> results.isLoaded())
                        .first()
                        .doOnNext((files) -> {
                            if (!incidents.containsKey("INCIDENT")) {
                                incidents.put("INCIDENT", new ArrayList<>());
                            }

                            incidents.get("INCIDENT").clear();
                            incidents.get("INCIDENT").addAll(realm.copyFromRealm(files));

                        })
                        .doOnTerminate(() -> {
                            Log.e(TAG, "Closing realm");
                            realm.close();
                        }))
                .doOnCompleted(() -> {
                    emitStoreChange(new CobaltStore.CobaltStoreChangeEvent());
                    Log.e(TAG, "EMIT INCIDENT");
                })
                .doOnError(error -> handleErrorEvent(error))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.from(backgroundLooper))
                .subscribe();

【问题讨论】:

    标签: android realm rx-java observable realm-mobile-platform


    【解决方案1】:

    1.) Realm.getDefaultInstance().asObservable()

    您获得了一个永远无法关闭的本地 Realm 实例,因此您正在泄漏内存。

    2.) 这不是 asObservable() 的设计方式。

    OnClickListener 完成并发出终端事件是否有意义?

    例如,您单击按钮一次,然后可观察对象“完成”并且永远不会再发出任何事件,即使用户随后单击按钮?

    当然不是,因此您也不应该期望 Realm 的 RealmChangeListener 提供它;这是绑定到 Realm 或 RealmResults 的内容,以便您可以收听未来对 Realm 或其特定表的任何写入。

    解决方案可能只是使用类似的东西

    Observable.fromCallable(() => {
        try(Realm realm = Realm.getDefaultInstance()) {
            RealmResults<FileDoc> docs = realm.where(FileDoc.class)
                 .isNull("parent")
                 .isNotNull("updatedDate")
                 .findAllSorted("name");
            documents.get("root").clear(); // <-- shouldn't you modify a new copy and return this?
            List<FileDoc> unmanagedDocs = realm.copyFromRealm(files);
            documents.get("root").addAll(unmanagedDocs);
            return unmanagedDocs;
        }
    }
    

    或者正如你所指出的,.filter((data) -&gt; data.isLoaded()).first() 也可以,虽然我没有想到。

    【讨论】:

    • 你指出了一个好点......但在我的情况下,我将它用作执行和结束的可完成的可观察对象......我不想担心永无止境的 Observable 停止出于任何原因(垃圾收集器或清理 android 中的内存)我发现解决我的问题的方法是调用 .first() 和 .filter(data.isLoaded) 并且我现在在 onTerminated() 关闭领域
    • 另外,我没有将值直接返回到主 UI 线程,而是有一个存储作为单一事实来源,并且 UI 会在进行更改时获取数据。 .
    • 查看我的更新答案,我将尝试遵循您的建议并对其进行修改以保持永无止境的可观察性,每次修改数据库时都会发出
    • 啊,我没想到filter().first(),但你是对的,它也会发出完成。您是否知道 Realm 被设计为一种反应式对象存储,它提供延迟加载的代理类,这些代理类始终指向相同的数据并提供更改侦听器,以便您可以侦听底层“单一事实来源”的更改?
    • 是的,但是我在使用 Observable 并尝试在主 UI 中访问生成的 RealmList 数据时迷失了方向,我总是收到 Realm objects can only be accessed on the thread they where created... 执行查询有什么意义如果数据必须留在该线程上,则在后台线程中?所以我开始制作我的结果的深拷贝,以便最终在 UI 线程中访问它...(使用 realm.copyFromRealm(files))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    相关资源
    最近更新 更多