Vibindas M
Vibindas M

Reputation: 493

How to call a method after a delay in android using rxjava?

I'm trying to replace my Handler method with RxJava.
My requirement:

I want to call the method getTransactionDetails() only after 5 seconds.

This my working code using Handler:

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

Rx java code - it's not working:

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

Upvotes: 43

Views: 56098

Answers (7)

Sergey M
Sergey M

Reputation: 93

Delay subscription already defined. Your example can be implemented in this way:

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

Upvotes: 7

Shashank Bhushan
Shashank Bhushan

Reputation: 141

If you want a disposable that can be used with the view then use a Completable Completable returns an Object which terminates as soon as one of the source Completables terminates (normally or with an error) and cancels all other Completables.

Eg :

Completable.timer(5, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
            .subscribe(() -> {
                // code after delay here
            });

If you want for a service to get complete i would recommend a Subscription

Eg :

observable.timer(5000, TimeUnit.MILLISECONDS)
    .map(o -> {
              // your code after delay here
              })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe( ()-<{
                   // enter the service here
                } );

Upvotes: 2

Geoffrey Marizy
Geoffrey Marizy

Reputation: 5521

doOnNext() is for side effects. It could be use for example for logging purpose, because logging doesn't alter the flow of data. But you want to pass down the result of getTransactionDetails(), so you should use map instead.

Second, Observable.empty() create an Observable that just propagate the finish/dispose message, it trigger neither doOnNext() neither map(). You could fix this using Observable.just() instead but a more idiomatic way would be to use Observable.timer():

Observable.timer(5000, TimeUnit.MILLISECONDS)
        .map(o -> getTransactionDetails())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe( ... );

A final note on Schedulers. Observable.timer() and delay() are executed on the computation scheduler by default so you don't need to call .subscribeOn(Schedulers.io()) to execute getTransactionDetails() outside of main thread. Observable.timer() and delay() could take a Scheduler as a parameter if you want to control this. So you need to call .observeOn(AndroidSchedulers.mainThread()) if you want to use getTransactionDetails() result on UI thread. Every operator after observeOn() is executed on the defined Scheduler, so you have to put observeOn() after computation.

Edit: This is of course if you care about the result of getTransactionDetails(). If not, see Clyde answer.

Upvotes: 63

Mr. Zahid
Mr. Zahid

Reputation: 39

Try this

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

Upvotes: 2

Clyde
Clyde

Reputation: 7549

This is how I would do it:

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

A Completable represents a deferred computation with no value but an indication for completion or exception. The static method call timer() returns a Completable that signals completion after the specified time period has elapsed, and the subscribe() call will mean that the method getTransactionDetails() will be called on the current object when the timer fires. By supplying a Scheduler as the last argument to Completable.timer() you control which thread is used to execute getTransactionDetails().

Upvotes: 91

Sergey Buzin
Sergey Buzin

Reputation: 255

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

you dont need observeOn because subscribe empty. use timer it will be more correct way

Upvotes: 13

xizzhu
xizzhu

Reputation: 895

It's not working, because delay() needs something to be emitted, but empty() actually emits nothing.

Instead, you should use Observable.timer().

Upvotes: 11

Related Questions