코코아의 우당탕탕 개발일지

[Android/Kotlin] 안드로이드 학습 5.1 - ViewModel & ViewModelProvider 본문

[Android]/학습

[Android/Kotlin] 안드로이드 학습 5.1 - ViewModel & ViewModelProvider

Cocoa's Story 2022. 12. 13. 04:04

뷰 모델 써보기!!

 

Android Kotlin Fundamentals: 5.1 ViewModel  |  Android Developers

In this codelab, you learn how to use ViewModel to enable data to survive configuration changes such as screen rotations in your Android Kotlin app.

developer.android.com

 

어떨 때 사용?

  • 수명주기를 고려한 방식으로 UI와 관련된 데이터를 저장할 때!
  • ViewModelFactory 클래스를 사용해서 뷰 모델 객체를 인스턴스화하고 반환함! 구성 변경 후에도 살아남도록!!

 

앱 상태 저장하기

지난 코드랩에서 다뤘던 onSaveInstanceState()콜백을 사용

->  상태를 번들에 저장하는 추가 코드를 작성하고 해당 상태를 검색하는 논리를 구현해야 함.

-> 저장할 수 있는 데이터의 양이 최소화됨

 

이번 코드랩에서 배울 앱 아키텍처 구성요소를 이용하면 위의 문제를 해결할 수 있음!!!

 

 

앱 아키텍처

  • 앱의 클래스들과 그들 사이의 관계를 디자인하는 방법
  • 안드로이드의 앱 아키텍처는 MVVM 아키텍처 패턴과 유사하다

UI 컨트롤러

  • Activity, Fragment 같은 UI 기반의 클래스
  • UI 컨트롤러는 뷰를 보여주거나 유저의 입력을 감지하는 등의 UI 및 운영 체제 상호 작용을 처리하는 논리만을 포함해야 함
  • 의사 결정 로직은 UI 컨트롤러에서 하지 말 것

ViewModel

  • 뷰모델은 뷰모델과 연결된 프래그먼트와 액티비티에 보여질 데이터를 보유한다
  • 간단한 계산 및 변환을 수행하여 UI 컨트롤러에서 표시할 데이터를 준비할 수 있음
  • 의사 결정을 수행할 수 있음

 

ViewModelFactory

  • ViewModelFactory는 ViewModel 객체를 인스턴스화함 (생성자 매개변수를 사용하거나/사용하지 않고)

 

사용

Step 1: GameViewModel 클래스 추가

1. gradle에 종속성 추가

//ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

2. screens/game/ 폴더 패키지에 GameViewModel이라는 새 kt 파일 만들기

3. GameViewModel 클래스가 abstract class ViewModel을 확장하게 하기

4. ViewModel에서 수명 주기를 인식하는 방법을 더 잘 이해할 수 있도록 log가 있는 init 블록 추가

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

Step 2: Override onCleared()

override fun onCleared() {
   super.onCleared()
   Log.i("GameViewModel", "GameViewModel destroyed!")
}

Step 3: GameViewModel을 game fragment와 연결

뷰모델은 UI 컨트롤러와 연결되어야 함!

둘을 연결시키려면 UI 컨트롤러 안에 뷰모델에 대한 참조를 만들어야 함

1. GameFragment 최상단에 GameViewModel을 클래스 변수로 추가

private lateinit var viewModel: GameViewModel

Step 4: ViewModel 초기화

화면 회전과 같은 구성 변경 중에 프래그먼트 같은 UI 컨트롤러가 다시 생성. 그러나 ViewModel 인스턴스는 살아남는다. ViewModel 클래스를 사용하여 ViewModel 인스턴스를 생성하면 프래그먼트가 다시 생성될 때마다 새 객체가 생성된다. 대신에, ViewModel 인스턴스는 ViewModelProvider을 사용해 생성됨

* 중요: ViewModel의 인스턴스를 직접 인스턴스화하기보다는 항상 ViewModelProvider로 ViewModel 객체를 만들 것!

 

1. ViewModel 초기화하기, ViewModelProvider.get() 메서드를 이용해 ViewModelProvider 생성

Log.i("GameFragment", "Called ViewModelProvider.get")
viewModel = ViewModelProvider(this).get(GameViewModel::class.java)

2. 앱을 실행하고 에뮬레이터를 돌려보자! (진짜 돌려보자)

-> GameFramgent는 매번 파괴 &  다시 생성되므로 ViewModelProvider.get()를 매번 호출. 그러나 GameViewModel은 한 번만 생성되며 호출할 때마다 다시 생성되거나 소멸되지 않음

3. 뒤로가기를 눌러보자. 게임을 종료하면 GameFragment가 파괴되고 연결된 항목인 GameViewModel도 소멸되고 onCleared() 콜백이 호출된다.

 

<ViewModelProvider의 작동 원리>

  • ViewModelProvider는 ViewModel이 이미 존재한다면 존재하는 ViewModel을 반환, 아니라면 새로 하나 만듦
  • ViewModelProvider는 주어진 범위(액티비티 또는 프래그먼트)와 관련된 ViewModel 인스턴스를 만듦
  • 생성된 ViewModel은 범위가 살아있는 한 유지됨

 

ViewModel 

 

 

더 알아보면 좋을 내용

Udacity course:

Android developer documentation:

Other: