Android Kotlin Fundamentals 05.1: ViewModel and ViewModelFactory 번역 #5

Task: Create the GameViewModel


뷰모델 클래스는 UI와 관련된 데이터들을 저장하고 관리하도록 구현 됩니다. 이 앱에서는 각 뷰모델은 각 프레그먼트들과 연관되어 있습니다.

 

이번 태스크에서 뷰모델을 앱에 추가 해 볼 것입니다. GameFragment를 위한 GameViewModel을 추가 해 볼 것입니다. 이 코드랩을 진행 하면서 ViewModel이 라이프 사이클을 알고 잇다는 것 또한 배우게 될 것 입니다.

 

Step1 : Add The GameViewModel class

 

1. build.gradle(module:app) 파일을 열고 아래 dependencies를 추가해 줍니다. ViewModel과 관련된 dependency입니다.  

//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'

 

2. screens/game 폴더 안에 GameViewModel 클래스를 생성해 주세요.

3. GameViewModle클래스는 추상 클래스인 ViewModel을 상속해야 합니다.

4. ViewModel은 라이프 사이클을 인지하고 있다는 것을 잘 이해 할 수 있도록 GameViewModel 클래스의 init 블록에 아래와 같이 log를 추가해 주세요.

 

class GameViewModel : ViewModel() {
   init {
       Log.i("GameViewModel", "GameViewModel created!")
   }
}

 

Step 2 : Override onCleared() and add logging

 

뷰모델은 연관되어 있던 프레그먼트가 detached 되었을 때 혹은 액티비티가 종료되었을 때, destroyed 됩니다. 뷰모델이 파괴되기 직전 onCleared() resources를 지우기 위해 콜백함수가 호출 됩니다.

 

  1. GameViewModel 클래스 안에 onCleared 함수를 override 해주세요.
  2. onCleared()안에 GameViewModel의 라이프사이클을 트래킹 할 수 있도록 로그를 추가 해 주세요.
override fun onCleared() {
   super.onCleared()
   Log.i("GameViewModel", "GameViewModel destroyed!")
}

 

Step 3: Associate GameViewModel with the game fagment

 

뷰모델은 UI 컨트롤러(프레그먼트 혹은 액티비티)와 연관이 되어있을 필요가 있습니다. 이 둘을 연관 짓기 위해서 UI 컨트롤러는 뷰모델을 참조하고 있어야 합니다.

 

이번 스텝에서는 GameViewModel 참조를 GameFragment에 추가해 보겠습니다. GameFragment 클래스에 상단에 아래와 같이 GameViewModel 필드를 추가해 줍니다.

 

private lateinit var viewModel: GameViewModel

 

Step 4: Initialize the ViewModel

 

화면 회전과 같이 설정 변경이 일어나는 동안 프레그먼트와 같은 UI 컨트롤러들은 재 생성 (re-created) 됩니다. 그러나 뷰모델 인스턴스는 살아 있습니다. 만약 뷰모델 인스턴스를 뷰모델 클래스를 사용해서 만들었다면, UI 컨트롤러 들이 재 생성 될 때 마다 뷰모델 또한 재생성 될 것입니다. 대신 ViewModelProvicer를 이용해서 뷰모델 인스턴스를 만들면 뷰모델은 UI 컨트롤러가 재생성 되더라도 살아 있습니다. 

 

 

중요 : 뷰모델을 인스턴스화 시키기 위해서는 ViewModel 오브젝트를 통해 바로 인스턴스화 시키기 보다는 ViewModelProvider를 이용해야 합니다. 

 

어떻게 ViewModelProvider가 동작하는지

  • ViewModelProvider는 ViewModel이 존재한다면, 존재하는 ViewModel을 리턴합니다. 존재하지 않는다면 새로운 뷰모델은 하나 생성합니다.
  • ViewModelProvider은 주어진 스코프(액티비티 혹은 프레그먼트)와 연관이 있는 뷰모델 인스턴스를 생성합니다.
  • 생성된 뷰모델은 스코프들(액티비티 혹은 프레그먼트)이 살아 있을 동안 유지 됩니다. 예를 들어 만약 스코프가 프레그먼트라면 뷰모델은 프레그먼트가 detached 될 때 까지 살아 있습니다.

ViewModelProviders.of()를 사용하여 ViewModelProvier를 만들고 ViewModel을 초기화 합니다.

 

  1. GameFragment 클래스에서 뷰모델 변수를 초기화 합니다. 아래의 코드를 onCreateView()에 넣습니다. binding 변수가 정의된 다음 줄에 넣으면 됩니다. ViewModelProviders.of()를 사용하고, GameFragment의 Context를 해당 함수의 인자로 보내줍니다. (this)
  2. ViewModel이 초기화 된 곳 위에 로그를 하나 찍어줍니다.
Log.i("GameFragment", "Called ViewModelProviders.of")
viewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)

 

3. 앱을 실행 시킵니다. 안드로이드 스튜디오에서 로그캣을 이용하여 "Game"으로 필터를 해서 로그를 살펴 봅니다. 로그캣에 보이는것 과 같이 GameFragment의 onCreateView()는 GameViewModel 인스턴스를 생성하는 ViewModelProviders.of()를 호출 합니다. 

 

4. 이제 화면 회전을 해봅시다. 화면 회전을 할 때마다 GameFragment는 destroyed 되고 re-created 됩니다. 그리고 ViewModelProviders.of()가 항상 호출 됩니다. 재생성 될 때 GameFRagment의 onCreateView()가 불리기 때문이죠. 그러나 GameViewModel은 오직 한번 생성됩니다. 그리고 여러번의 화면 회전에도 더 이상 재생성 되거나 파괴되지 않습니다.

 

 

5. 게임을 나가 봅시다. GameFragment가 destroyed 될 것입니다. 그리고 연관된 ViewModel 역시 destroyed 됩니다. 이때 뷰모델이 가지고 있는 onCleared()가 호출 됩니다.

 

 

 

댓글



Designed by JB FACTORY