본문 바로가기
개인공부/android

[Kotlin] Coroutine을 이용한 간단한 타이머

by 왕큰새 2022. 2. 16.
728x90

1. 시작 버튼을 클릭했을 때, System의 현재 시간을 StartTime 변수에 저장하고

   인수로 시작 시간을 주어, Timer를 시작시킨다. 


2. Coroutine Scope 안에서 while문을 실행시켜 System의 시간을 Delay를 이용 계속 갱신한다.

   이때 화면에 표시될 시간은 Scope 안에서 [ 갱신된 System의 시간 - 인수로 전달된 시간 ]이 될 것이다.

 

3. 이미 시작이 된 경우, 중지 또는 타이머를 재개시킨다. 

   이때, 재개시키는 경우의 시간은 중지가 된 시점부터, System의 시간을 뺀 값이다.

   그 후, Timer에게 재개 시간을 인수로 주어, Timer를 다시 시작한다.

    private var isStart = false
    private var startTime = 0L
    private var isNotPaused = true
    private var pauseTime: Long = 0L
    private var resumeTime: Long = 0L
    
    
	startBtn.setOnClickListener {
            if(!isStart) { // 시작되지 않았다면
                startTime = System.currentTimeMillis()
                startTimer(startTime)
                binding.startBtn.setImageResource(R.drawable.ic_baseline_pause_24)
            } else { // 이미 타이머가 시작된 상태라면
                if(isNotPaused) {
                    pauseTimer()
                    isNotPaused = !isNotPaused
                    binding.startBtn.setImageResource(R.drawable.ic_baseline_play_arrow_24)
                } else {
                	startTime  = resumeTime
                    startTimer(resumeTime)
                    isNotPaused = !isNotPaused
                    binding.startBtn.setImageResource(R.drawable.ic_baseline_pause_24)
                }
            }
        }



fun startTimer(time:Long) {
    lifecycleScope.launch(Dispatchers.Main) {
        while (isNotPaused) {
            binding.timerView.text = (System.currentTimeMillis()-time).displayTime()
            delay(INTERVAL)
        }
    }
    isStart = true
}
fun pauseTimer() {
    pauseTime = (System.currentTimeMillis() - startTime)
    binding.timerView.text = pauseTime.displayTime()
    lifecycleScope.launch(Dispatchers.Main) {
        while(true) {
            resumeTime = System.currentTimeMillis() - pauseTime
            delay(INTERVAL)
        }
    }
}
fun Long.displayTime(): String {
    if (this <= 0L) {
        return START_TIME
    }
    val h = this / 1000 / 3600
    val m = this / 1000 % 3600 / 60
    val s = this / 1000 % 60
    val ms = this % 1000 / 10

    return "${displaySlot(h)}:${displaySlot(m)}:${displaySlot(s)}:${displaySlot(ms)}"
}

private fun displaySlot(count: Long): String {
    return if (count / 10L > 0) {
        "$count"
    } else {
        "0$count"
    }
}

활용한 코드 출처 - https://github.com/ziginsider/Foreground-Service-Demo-Android-App