경험의 기록

타이머가 작동하면서 다른 코드도 동작해야 하기 때문에 타이머는 비동기 처리 방식으로 구현해야한다.

2021.03.30 - [코틀린] - [Kotlin] 코틀린 비동기 처리 (코루틴)

 

[Kotlin] 코틀린 비동기 처리 (코루틴)

여러개의 구문을 동시에 실행하고 싶다면 코루틴을 사용해야한다. 코루틴의 Scope 코루틴은 제어범위 및 실행범위를 지정할 수 있다. GlobalScope : 프로그램 어디서나 동작,제어가 가능한 기본 범위

hanyeop.tistory.com

코루틴에 대한 간략한 글은 이 곳에 정리하였다.

 

MVVM 패턴을 기반으로 작성할 것이다.

2021.04.26 - [안드로이드/기본] - [Android] 안드로이드 ViewModel, LiveData (+DataBinding)

 

[Android] 안드로이드 ViewModel, LiveData (+DataBinding)

2021.04.19 - [안드로이드/기본] - [Android] 안드로이드 AAC & MVVM [Android] 안드로이드 AAC & MVVM 액티비티, 프래그먼트에 너무 많은 코드를 넣게 되면 점점 무거워져 다루기 힘들어지게 된다. 앱이 카메라.

hanyeop.tistory.com


사용해보기

dependencies 추가

def lifecycle_version = "2.3.0"

    // ViewModel - 라이프 사이클
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData - 데이터의 변경 사항을 알 수 있음
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    // 코루틴
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'

뷰모델과 라이브데이터, 코루틴을 사용할 것이기 때문에 dependencies 추가해준다.

 

DataBinding 추가

// 데이터바인딩
    buildFeatures {
        dataBinding true
    }

데이터바인딩을 사용할 것이기 때문에 bulid.gradle (Module)  android에 추가해준다.

 

레이아웃

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="org.techtown.coroutineTest.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/timer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(viewModel.timerCount)}"
            app:layout_constraintBottom_toBottomOf="parent"
            android:textSize="30sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.226" />

        <Button
            android:id="@+id/startButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="36dp"
            android:text="타이머 시작"
            android:textSize="19sp"
            android:onClick="@{() -> viewModel.timerStart()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/timer" />

        <Button
            android:id="@+id/pauseButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:text="타이머 정지"
            android:textSize="19sp"
            android:onClick="@{() -> viewModel.timerStop()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/startButton" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

타이머 텍스트뷰와 타이머를 시작하고 정지할 수 있는 버튼을 추가한다.

타이머는 뷰모델에 있는 라이브데이터에 바인딩해주고, 버튼도 각각 메소드에 바인딩해준다.

 

뷰모델

class MainViewModel : ViewModel() {
    private val _timerCount = MutableLiveData<Int>()
    private lateinit var a : Job

    // Getter
    val timerCount : LiveData<Int>
        get() = _timerCount

    init{
        _timerCount.value = 5
    }

    fun timerStart(){
        if(::a.isInitialized) a.cancel()

        _timerCount.value = 5
        a = viewModelScope.launch {
            while(_timerCount.value!! > 0) {
                _timerCount.value = _timerCount.value!!.minus(1)
                delay(1000L)
            }
        }
    }

    fun timerStop(){
        if(::a.isInitialized) a.cancel()
    }
}

스타트 클릭시

1초당 타이머를 1씩 감소시킨다.

viewModelScope는 해당 ViewModel이 onClear시 같이 취소된다.

 

메인액티비티

class MainActivity : AppCompatActivity() {

    lateinit var mainViewModel: MainViewModel
    lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)

        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        binding.viewModel = mainViewModel

        binding.lifecycleOwner = this
    }
}

뷰모델을 연결하여 옵저빙한다.

감소된 타이머값이 UI에 실시간으로 반영된다.

 

github.com/HanYeop/AndroidStudio-Practice/tree/master/Coroutine_Test

 

HanYeop/AndroidStudio-Practice

안드로이드 학습 내용 저장소. Contribute to HanYeop/AndroidStudio-Practice development by creating an account on GitHub.

github.com

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading