24

In android i use Timer to execute task that repeats every 5 seconds and starts after 1 second in this way:

    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            // Here is the repeated task
        }
    }, /*Start after*/1000, /*Repeats every*/5000);

    // here i stop the timer
    timer.cancel();

this timer will repeat Until i call timer.cancel()

I am learning RxJava with RxAndroid extension

So i found this code on internet, i tried it and it doesnt repeat:

Observable.timer(3000, TimeUnit.MILLISECONDS)
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Long>() {
        @Override
        public void call(Long aLong) {
             // here is the task that should repeat
        }
    });

so what is the alternative for the android Timer in RxJava.

MBH
  • 16,271
  • 19
  • 99
  • 149

5 Answers5

61

timer operator emits an item after a specified delay then completes. I think you looking for the interval operator.

Subscription subscription = Observable.interval(1000, 5000, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Long>() {
                public void call(Long aLong) {
                    // here is the task that should repeat
                }
            });

if you want to stop it you just call unsubscribe on the subscription:

subscription.unsubscribe()
csabapap
  • 1,031
  • 1
  • 9
  • 14
  • 27
    You don't need `.subscribeOn(Schedulers.io())` to start in background because `Observable.interval` emits on `Schedulers.computation()` by default. – Dave Moten Jul 27 '16 at 09:42
  • 5
    in RX 2 instead of Action1 you should use Consumer – Ponomarenko Oleh Nov 13 '18 at 19:12
  • It's worth mentioning that the first param is the initial delay. public static Observable interval(long initialDelay, long period, TimeUnit unit) { return interval(initialDelay, period, unit, Schedulers.computation()); } – omersem Oct 27 '21 at 20:57
11

Call Observable.repeat() method to repeat

Disposable disposable = Observable.timer(3000, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.newThread())
.repeat()
.observeOn(AndroidSchedulers.mainThread())
.subscribe();

If you want to stop it call disposable.dispose()

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Anshuman
  • 111
  • 1
  • 4
3

KOTLIN way

Observable.timer(5000, TimeUnit.MILLISECONDS)
            .repeat() //to perform your task every 5 seconds
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                Log.d("ComingHere", "Inside_Timer")
            }
Sachin Rajput
  • 4,326
  • 2
  • 18
  • 29
1

This is the right and secure way %100 working :

     //timer variable is in seconds unit
    int timer = 5;
    Disposable disposable = Observable.interval(timer, TimeUnit.SECONDS)
            .map((tick) -> {
                handler.post(() -> {
                    //Enter your CODE here !!!
                });
                return true;
            }).subscribe();

And for stoping it :

if (disposable != null) {
        disposable.dispose();
    }
ParSa
  • 1,118
  • 1
  • 13
  • 17
0

I create this method for send time from viewModel to View :

fun countTime(start: Boolean) {
        var counter = 0
        var seconds: Int
        var minutes: Int
        if (start) {
            disposable = Observable.timer(1, TimeUnit.SECONDS)
                .repeat()
                .subscribe {
                    counter++
                    seconds = (counter % 60)
                    minutes = (counter % 3600) / 60
                    val secondFormatter = String.format("%02d", seconds)
                    val minutesFormatter = String.format("%02d", minutes)
                    timeLiveData.postValue(" $minutesFormatter : $secondFormatter")
                }
        } else {
            if (disposable != null) {
                timeLiveData.postValue("00 : 00")
                disposable.dispose()
            }
        }
    }