[Kotlin] 안드로이드 ViewModel 사용하기

개발세발·2022년 9월 28일
0

안드로이드개발

목록 보기
2/5

ViewModel


먼저 ViewModel을 적용하지 않았을 때와 적용했을 때의 차이점을 확인해보자.

해당 화면은 "입력" 버튼을 누르면 입력한 수를 결과값에 더하는 과정이다.

ViewModel 적용 전

ViewModel 적용 후


화면 회전을 하는 경우 입력되었던 결과값이 초기화되는 것을 볼 수 있다.

이런 현상은 안드로이드의 Life Cycle과 연관되어있다.

https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ko

안드로이드 개발자 문서에 따르면 화면회전(Activity rotated)되면 기존 활동을 소멸시키고 새로 생성 하게 된다. 즉, 기존 활동에 존재했던 데이터는 초기화 된다는 것이다.

이런 현상을 방지하기 위해 ViewModel 객체를 사용한다.
화면이 회전되어 새로 onCreate()가 불러와져도 ViewModel 객체에 담긴 데이터는 유지되기 때문에 기존 데이터를 보존할 수 있게 된다.

참고: ViewModel이 onCleared() 되는 시기

ViewModel의 onCleared()는 ViewModel이 더 이상 필요하지 않을 때 호출된다.
시스템의 메모리를 확보하기 위해 앱이 백그라운드로 전환되고 앱 프로세스가 종료될 때와 사용자가 finish()를 호출할 때 ViewModel이 onCleared()된다.

또한 back button을 클릭하면 현재 activity의 ViewModel이 사라진다.




사용법


app 수준의 Build.gradle 파일 작성

dependencies {
    def lifecycle_version = "2.6.0"

    // ViewModel
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
    // LiveData
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
    
    ...
}

최신버전은 공식문서에서 확인이 가능하다.


xml 파일

<?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="addNum"
            type="com.seunggyu.viewmodeldemo2.MainActivity" />
    </data>

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

        <EditText
            android:id="@+id/et_num"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:hint="@string/inputNum"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/btn_input"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="15dp"
            android:text="@string/inputButton"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/et_num" />

        <TextView
            android:id="@+id/tv_total"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:text="0"
            android:textColor="@color/black"
            android:textSize="24sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/btn_input" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

그냥 일반적이면서 단순한(?) xml 파일이다.


ViewModel 파일

ViewModel 파일에는 자바로 치면 게터(getter)와 세터(setter)를 작성한다.

import androidx.lifecycle.ViewModel

class MainActivityViewModel : ViewModel() {
    private var total = 0

    fun getTotal(): Int{
        return total
    }

    fun setTotal(input: Int){
        total += input
    }
}

Activity 파일

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MainActivityViewModel // ViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)

        binding.apply {
            tvTotal.text = viewModel.getTotal().toString()

            btnInput.setOnClickListener {
                viewModel.setTotal(binding.etNum.text.toString().toInt())
                tvTotal.text = viewModel.getTotal().toString()
            }
        }
    }
}

viewModel 객체는 ViewModelProvider를 이용해 만든다.
ViewModelProvider 인자로는 this를 넘겨주는데 여기서 this는 ViewModelStore의 소유자를 의미한다.
다시 말해 MainActivity가 ViewModelStore의 소유자 라고 알려주는 것과 같다.

profile
좋은 개발자가 되기 위한 세 걸음

0개의 댓글