Android Rxjava interval 로 타이머 만들어보기

Android Rxjava interval 로 타이머 만들어보기

반응형

내가 작업하는 앱에는 시간과 관련된 기능이 많다.

시간이 완료되면 다음 단계로 넘어가야하는 그런 작업이 상당히 많다.

이전까지는 제한시간이 2분 미만인 경우가 많아서

안드로이드에서 제공해주는 CountDownTimer 를 사용했었다.

그런데 최근에 제한시간이 1시간이 넘는 테스크가 생겼다.

동일하게 CountDownTimer로 적용을 해보니 뭔가 이상하다...시간이 한 80초 이상 넘어가면 가끔씩 시간이 맞지 않는것처럼 느껴질때가 있었다. 예를 들어 내가 280초로 설정을 해놓고 시간이 감소되는걸 보면 가끔씩 1초,2초가 빌때가 있다.

구글링을 해보니 CountDownTimer 의 고질적인 문제인듯 하다.

시간이 중요한 작업이라 고민을 하다 RxJava interval로 만들어 보는것을 생각했다.

구현하고 테스트해보니 크게 문제없이 잘 나오는거 같다.

구현방법은 모두 다르겠지만 나같은 경우에는 TextView를 상속받고 그 안에 Rx interval을 구현하는 식으로 작업했다.

import android.content.Context import android.graphics.Color import android.util.AttributeSet import androidx.appcompat.widget.AppCompatTextView import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.schedulers.Schedulers import java.util.concurrent.TimeUnit class RxTimerView @JvmOverloads constructor( context: Context, attr : AttributeSet, defStyleInt: Int = 0 ) : AppCompatTextView(context,attr,defStyleInt) { private val compositeDisposable: CompositeDisposable = CompositeDisposable() var timerListener: TimerListener? = null init { setTextColor(Color.BLACK) } var time: Long = 0L set(value) { field = value //포맷형식에 따라 여러가지 시간표현가능 val hh = "%02d".format((field / 1000) / 60 / 60 % 24) val mm = "%02d".format((field / 1000) / 60 % 60) val ss = "%02d".format((field / 1000) % 60) this.text = "남은시간 $hh:$mm:$ss" } fun startTimer(millisTime: Long) { compositeDisposable.add( Observable.interval(0 , 1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe { time = millisTime - (it*1000) timerListener?.getTime(time) if (time < 1000L) compositeDisposable.clear() } ) } fun stopTimer(){ compositeDisposable.clear() time = 0 } interface TimerListener { fun getTime(time: Long) } }

사용법은 TextView를 상속했기 때문에 xml에서 일반 TextView 쓰듯이 쓰면된다.

액티비티 단에서는 아래처럼 쓰면 된다.

binding.timer.startTimer( 7202 * 1000 ) // 7202 초 * 1000 현재 작업한 형식대로면 02시간 00분 02초 동작체크 binding.timer.stopTimer() //타이머 중지 binding.timer.timerListener = object : RxTimerView.TimerListener{ override fun getTime(time: Long) { //시간이 감소될때마다 해당 리스너로 감지된다. } }

혹시라도 더 좋은 타이머 구현 방법이나 팁이 있다면 공유부탁합니다.

반응형

from http://choi3950.tistory.com/46 by ccl(A) rewrite - 2021-10-14 00:27:26