RXJava 2调用了两次

时间:2017-04-28 08:44:00

标签: java android rx-java rx-java2

我仍在尝试将RXJava 2用于多个订阅者使用的轮询服务。除了它总是被调用两次之外它运作良好。

我尝试使用publish(1),take(1),share(),refCount()等,但结果总是一样的。叫两次或多次。

我仍然不明白为什么它被召唤两次。新订阅者应该接收最新发布的值,并且仅在更改后的值(如果更改了hashmap)返回为修改后的列表。

我的民意调查(单身人士)

public Observable<List<Light>> lightPolling = CallFactory
            .with(context)
            .getLights(MainApplication.lastaccespoint)
            .repeatWhen(o -> o.concatMap((Function<Object, ObservableSource<?>>) v -> Observable.timer(1000, TimeUnit.MILLISECONDS)))
            .filter(new MapPredicate<>())
            .distinctUntilChanged()

            .map(l -> {
                List<Light> lights = new ArrayList<>();
                for (Map.Entry<String, Light> entry : l.entrySet()) {
                    Light light = entry.getValue();
                    light.setId(entry.getKey());
                    lights.add(light);
                }
                return lights;
            })
            // .replay(1)
            //    .distinct()
            //.publish()
            //.share()
            .compose(ReplayingShare.instance()); // its like .share(), just including the last result etc.

如果哈希映射真的发生了变化,我的Predicate用于过滤。 StringUtil.equalMap只是一个比较两个效果良好的哈希图的简单方法。

 class MapPredicate<T> implements Predicate<Map<String, T>> {

    private Map<String, T> lastMap;

    @Override
    public boolean test(Map<String, T> map) throws Exception {
        if (!StringHelper.equalMap(map, lastMap)) {
            Timber.d("Result in MapPredicate doesnt equals last result");
            lastMap = map;
            return false;
        }
        return true;
    }
}

最后我的Disposable订阅了Observable。

lightsDisposable = LightManager
            .getInstance(context)
            .lightPolling
            .subscribeWith(new BulbsObserver());

更多用于测试

 LightManager.getInstance(context).lightPolling.debounce(10, TimeUnit.SECONDS).subscribe(lights -> Timber.d("Received light second Subscriber "+ lights.size()));
 LightManager.getInstance(context).lightPolling.debounce(15, TimeUnit.SECONDS).subscribe(lights -> Timber.d("Received light Third Subscriber "+ lights.size()));

当然是我的观察员

private class BulbsObserver extends DisposableObserver<List<Light>> {

    @Override
    public void onNext(List<Light> newLights) {
        Timber.d("Received lights=" + newLights.size());
        lights.clear();
        lights.addAll(newLights);
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onError(Throwable throwable) {
        Timber.e(throwable);
    }

    @Override
    public void onComplete() {
        Timber.d("onComplete called");
    }
}

重播分享来自杰克沃顿https://github.com/JakeWharton/RxReplayingShare

1 个答案:

答案 0 :(得分:4)

每当第一个订阅者到来时,

refCount()订阅(调用subscribe函数),并在最后一个订阅者离开后取消订阅。如果您的订阅者按顺序进行(即引用计数在它们之间降至零),您将遇到对原始源的多个订阅/取消订阅。

如果您只想订阅一次且从不取消订阅,请使用autoConnect()代替refCount()。例如:

hotObservable = coldObservable.replay(1).autoConnect();