wegtis
wegtis

Reputation: 333

Android convert basic timer to RxJava

I hava created a simple timer, which count from 0 to 30 with interval of 1 second. I want to achive the same, but it must be count from 30 to 0 and it must be done with a RxJava. Can someone provide me sample convertion?

Here is my code:

 TextView timerTextView;
long startTime = 0;

//runs without a timer by reposting this handler at the end of the runnable
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {

    @Override
    public void run() {
        long millis = System.currentTimeMillis() - startTime;
        int seconds = (int) (millis / 1000);
        int minutes = seconds / 60;
        seconds = seconds % 60;

        timerTextView.setText(String.format("%d:%02d", minutes, seconds));

        timerHandler.postDelayed(this, 500);
    }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    timerTextView = (TextView) findViewById(R.id.textView);

    Button b = (Button) findViewById(R.id.button);
    b.setText("start");
    b.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Button b = (Button) v;
            if (b.getText().equals("stop")) {
                timerTextView.setText("0:00");
                timerHandler.removeCallbacks(timerRunnable);
                b.setText("start");
            } else {
                startTime = System.currentTimeMillis();
                timerHandler.postDelayed(timerRunnable, 0);
                b.setText("stop");
            }
        }
    });

    timerTextView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if(timerTextView.getText().toString().equals("0:30")){
                Toast.makeText(MainActivity.this, "End of time!", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });
}

Upvotes: 1

Views: 1042

Answers (2)

akarnokd
akarnokd

Reputation: 69997

It doesn't have to be complicated:

Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.take(31) // 0, 1, 2, ..., 30
.map(new Func1<Long, Integer>() {
     @Override public Integer call(Long value) {
         return 30 - value.intValue();
     }
})
.subscribe(new Action1<Integer>() {
     @Override public void call(Integer value) {
          System.out.println(value);
     }
});

Upvotes: 2

ROBOHORSE
ROBOHORSE

Reputation: 11

Hm, i don't know how to use reverse range, but the simple way is to use following:

 final int startCount = 30;
 final Observable<Integer> observable = Observable
            .range(0, startCount)
            .concatMap(
                    i -> Observable.just(i)
                            .delay(1, TimeUnit.SECONDS)
                            .map(it -> startCount - it)
            );

 final Subscription subscription = observable.subscribe(System.out::println);

and unsubscribe when onStop() invoked

@Override
public void onStop(){
    subscription.unsubscribe();
}

or without lambda:

 final int startCount = 30;
 final Observable<Integer> observable = Observable
            .range(0, startCount)
            .concatMap(new Func1<Integer, Observable<? extends Integer>>() {
                           @Override
                           public Observable<? extends Integer> call(Integer integer) {
                               return Observable.just(integer)
                                       .delay(1, TimeUnit.SECONDS)
                                       .map(new Func1<Integer, Integer>() {
                                           @Override
                                           public Integer call(Integer integer) {
                                               return startCount - integer;
                                           }
                                       });
                           }
                       }
            );

 final Subscription subscription = observable
            .subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                    System.out.println(integer);
                }
            });

and of course apply schedulers for observable

.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())

Upvotes: 0

Related Questions