RxJava轮询+手动刷新

时间:2017-09-20 09:53:50

标签: java android rx-java polling

我有一个列表想要每分钟刷新一次。 例如,用户列表在此处:https://github.com/android10/Android-CleanArchitecture/blob/master/domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/GetUserList.java

我使用repeatWhen添加定期刷新:

  public Observable<List<User>> buildUseCaseObservable(Void unused) {
    return this.userRepository
        .users()
        .repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
          @Override
          public ObservableSource<?> apply(Observable<Object> objectObservable) throws Exception {
            return objectObservable.delay(1, TimeUnit.MINUTES);
          }
        });
  }

这样工作正常,每分钟调用onNext。 但是,如果我想立即刷新此列表(由于用户的操作或因为通知),我不知道如何执行此操作。

我应该取消/处置observable并重启一个新的吗? 感谢

2 个答案:

答案 0 :(得分:2)

从您的代码中我了解用户列表是在订阅时生成和发出的。

以下是我能想到的一些解决方案,而不是取消订阅和重新订阅您想立即做出反应的事件:

  1. 不使用repeatWhen运算符,而是使用interval creation operatorflatMap结合使用,每分钟调用一个新的Observable订阅并使用merge运算符以添加对您感兴趣的其他事件的反应。像这样:

    @Test
    public void intervalObservableAndImmediateReaction() throws InterruptedException {
        Observable<String> obs = Observable.interval(1, TimeUnit.SECONDS)
                    .cast(Object.class)                                          
                    .mergeWith(
                              Observable.just("mockedUserClick")
                                        .delay(500, TimeUnit.MILLISECONDS))
                    .flatMap(
                             timeOrClick -> Observable.just("Generated upon subscription")
                             );
    
        obs.subscribe(System.out::println);
        Thread.currentThread().sleep(3000); //to see the prints before ending the test
    }
    

    或根据您的需要进行调整(但校长相同):

    Observable.interval(1, TimeUnit.MINUTES)
                .mergeWith(RxView.clicks(buttonView))
                .flatMap(timeOrClick -> this.userRepository.users());
    
  2. 您可以像以前一样使用flatMap运算符,即使在保持当前实现工作且不合并间隔的情况下 - 只需保留您的工作代码,并将其保存在程序链的另一个区域中{您选择的{3}}:

    RxView.touches(yourViewVariable)
          .flatMatp(motionEvent -> this.userRepository.users())
          .subscribe(theObserver);
    

    请注意,在此解决方案中,订阅是独立于两个可观察者完成的。如果您使用不同的观察者,或者管理该主题或某事物,您可能会更好。我运行的一个小测试表明,一个订阅者处理了订阅2个不同的observable而没有问题(在Rxjava1中 - 还没有检查Rxjava2),但是对我来说感觉不错。

答案 1 :(得分:1)

如果您不关心在其他一个可观察数据发出数据后调整刷新时间,您可以执行以下操作:

    // Specific example of a user manually requesting
    val request = Observable.create<String> { emitter ->
        refresh.setOnClickListener {
            emitter.onNext("Click Request")
        }
    }
            .observeOn(Schedulers.io())
            .flatMap {
                userRepository.users()
            }

    // Refresh based off of your original work, could use something like interval as well
    val interval = userRepository.users()
            .subscribeOn(Schedulers.io())
            .repeatWhen { objectObservable ->
                objectObservable.delay(1, TimeUnit.MINUTES)
            }

    // Combine them so that both emissions are received you can even add on another source
    Observable.merge(request,interval)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                contents.text = it.toString()
            }, {
                contents.text = it.toString()
            },{
                println(contents.text)
            })

然后您不必每次都处置和重新订阅