如何使用RxJava在Android中延时调用方法?

42

我想用RxJava替换我的Handler方法。
我的要求:

我想在5秒后调用getTransactionDetails()方法。

这是我使用Handler的工作代码:

new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        getTransactionDetails();
      }
    }, 5000); 

RxJava代码 - 它不能正常工作:

Observable.empty().delay(5000, TimeUnit.MILLISECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext(o -> getTransactionDetails())
        .subscribe();

这可能会有所帮助:https://dev59.com/XZDea4cB1Zd3GeqPal0b - Charuක
使用RxJava2的delaySubscription方法:.delaySubscription(5000, TimeUnit.MILLISECONDS) - Dmitriy Pavlukhin
7个回答

90

这是我会做的方式:

    Completable.timer(5, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
        .subscribe(this::getTransactionDetails);

Completable表示一个延迟计算,没有值,但有完成或异常的指示。静态方法调用timer()返回一个Completable,在经过指定的时间后信号完成,而subscribe()调用将意味着当计时器触发时,将在当前对象上调用getTransactionDetails()方法。通过在Completable.timer()的最后一个参数中提供Scheduler,您可以控制使用哪个线程来执行getTransactionDetails()


62

doOnNext() 用于产生副作用。例如,它可以用于记录日志,因为日志记录不会更改数据流的流向。但是,如果您要传递 getTransactionDetails() 的结果,则应改用 map。

其次,Observable.empty() 创建一个只传播完成 / 释放消息的 Observable,它既不触发 doOnNext() 也不触发 map()。您可以使用 Observable.just() 来解决这个问题,但更本质的方法是使用 Observable.timer()

Observable.timer(5000, TimeUnit.MILLISECONDS)
        .map(o -> getTransactionDetails())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe( ... );
关于调度程序的最后说明。默认情况下,Observable.timer()delay()在计算调度程序上执行,因此您不需要调用.subscribeOn(Schedulers.io())来在主线程之外执行getTransactionDetails()。如果您想要控制Observable.timer()delay(),则可以将Scheduler作为参数传递。因此,如果您想在UI线程上使用getTransactionDetails()结果,则需要调用.observeOn(AndroidSchedulers.mainThread())observeOn()之后的每个操作都在定义的Scheduler上执行,因此您需要将其放在计算后面。 编辑:当然,如果您不关心getTransactionDetails()的结果,请参见Clyde答案。

1
地图应该放在observeOn之前,这样它就可以在RxComputation线程上运行,而不是主线程上运行。 - skeeve
@GeoffreyMarizy 我该如何在每天凌晨12点调用它? - Nouman Ch
据我所知,RxJava不支持这种用例。这是有道理的,因为Rx不过是一个(超级加强版的)观察者模式。 - Geoffrey Marizy
真正帮助我理解问题的部分是关于调度程序的部分;已赞。 - Antek

13
Observable
     .timer( 5000, TimeUnit.MILLISECONDS )
     .subscribeOn(Schedulers.io())
     .map(o -> getTransactionDetails() )
     .subscribe();

你不需要使用 observeOn,因为订阅的是空值。 使用 timer 会更加正确。


1
为什么你在.map中执行函数而不是在.subscribe()中执行? - David Luque

11
它不能工作,因为delay()需要发出一些东西,但empty()实际上什么都没有发出。

相反,您应该使用Observable.timer()


4
或者 Completable.complete().delay(...) - Kiskae

7

延迟订阅已经定义。您可以按照以下方式实现示例:

getTransactionDetails().delaySubscription(5000, TimeUnit.MILLISECONDS)

2
如果您想使用视图与可丢弃的对象,则请使用Completable。 Completable返回一个对象,该对象在源Completables之一终止(正常或出现错误)时终止,并取消所有其他Completables。
例如:
Completable.timer(5, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
            .subscribe(() -> {
                // code after delay here
            });

如果您希望服务得到完整的支持,我建议您订阅。
例如:
observable.timer(5000, TimeUnit.MILLISECONDS)
    .map(o -> {
              // your code after delay here
              })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe( ()-<{
                   // enter the service here
                } );

2

试试这个

Observable.just(true).delay(5000, TimeUnit.MILLISECONDS)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .map(o -> getTransactionDetails())
    .subscribe();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接