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

사용자가 게임을 끝내고 ScoreFragment로 이동 하였을 때, 점수가 보이지 않았습니다. ScoreFragment에서 표시 할 점수를 ViewModel이 가지고 있도록 해야 합니다. 팩토리 메소드 패턴을 이용하여 뷰모델을 초기화 하는 동안 점수 값을 전달 해 봅시다.

 

팩토리 메소드 패턴은 팩토리 메소드를 사용하여 오브젝트를 생성하는 패턴입니다. 이 방법은 같은 클래스의 인스턴스를 반환 합니다.

 

이번 태스크에서는 파라미터를 전달 하여  Score Fragment와 연관이 있는 뷰모델을 생성할 것입니다. 그리고 팩토리 메소드는 뷰모델을 초기화 합니다.

 

1. score 패키지 안에 ScoreViewModel 클래스를 만드세요. 이 클래스는 score fragment를 위한 뷰모델이 될 것입니다.

 

2. ScoreViewModel은 ViewModel 클래스를 상속 해야 합니다. 그리고 생성자에 파라미터를 추가 해 보세요. 그리고 init 블록에 로그를 추가 하여 보세요.

 

3. ScoreViewModel 클래스 안에 score를 저장 할 수 있는 변수를 추가 해 주세요.

class ScoreViewModel(finalScore: Int) : ViewModel() {
   // The final score
   var score = finalScore
   init {
       Log.i("ScoreViewModel", "Final score is $finalScore")
   }
}

 

4. score 패키지 안에 ScoreViewMdoelFactory 클래스를 추가 해 주세요. 이 클래스는 ScoreViewModel을 초기화 하는 역할을 합니다.

 

5. ScoreViewModelFactory 클래스는 ViewModelProvider.Factory를 상속합니다. 그리고 final score(화면에 그려져야 하는)를 위한 생성자 파라미터를 추가 해주세요.

 

class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory {
}

 

6. ScoreViewModelFactory에서 안드로이드 스튜디오는 구현되지 않은 것이 있다는 에러를 띄워 줄 것 입니다. 이를 해결 하기 위해 create() 메소드를 오버라이드 해 줍니다. 이 create() 메소드는 새롭게 생성된 ScoreViewModel을 리턴 해 줍니다.

 

override fun <T : ViewModel?> create(modelClass: Class<T>): T {
   if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {
       return ScoreViewModel(finalScore) as T
   }
   throw IllegalArgumentException("Unknown ViewModel class")
}

 

7. ScoreFragment에서 ScoreViewModel과 ScoreViewModelFactory를 위한 변수를 생성 해 줍니다.

private lateinit var viewModel: ScoreViewModel
private lateinit var viewModelFactory: ScoreViewModelFactory

 

8. ScoreFragment의 onCreateView() 안에서 binding 변수를 초기화 하는 코드 아래에 viewModelFactory를 초기화 해주세요. 이 때 viewModelFactory를 초기화 하기 위해 ScoreViewModelFactory를 사용 해야 합니다. argument bundle로 부터 ScoreViewModelFactory()의 생성자 파라미터로 final score 데이터를 전달 합니다.

viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score)

9. onCreateView() 안에서 viewModelFactory를 초기화 한 후에, ViewModelProviders.of()를 호출 하여 viewModel 오브젝트를 초기화 해 줍니다. 이 때,  관련된 프레그먼트의 context와 viewModelFactory를 전달 해 줍니다. 이러한 코드는 viewModelFactory 클래스 안에 정의 된 ScoreViewModel 오브젝트의 인스턴스를 생성 할 것 입니다.

 

viewModel = ViewModelProviders.of(this, viewModelFactory)
       .get(ScoreViewModel::class.java)

 

10. onCreateView() 안에서 viewModel이 초기화 된 다음 scoreText를 셋팅 하는 코드를 넣어 봅시다. 해당 score는 ScoreViewModel 안에 정의 되어 있습니다.

 

binding.scoreText.text = viewModel.score.toString()

 

11. 이제 앱을 실행 하고, 게임을 끝내 거나 End Game 버튼을 누르게 되면 score fragment는 final score를 보여 줄 것입니다.

 

 

이 앱에서는 ScoreViewModel을 위해 ViewModelFactory를 추가 하는 것은 불필요 합니다. 왜냐하면 viewModel.score에 데이터를 바로 할당 할 수 있기 때문입니다. 그러나 때때로 ViewModel이 초기화 될 때 데이터가 필요할 수도 있습니다.

 

이번 태스크에서는 ViewModel을 사용하여 ScoreFragment를 구현 했습니다. 어떻게  뷰모델 팩토리를 통해 파라미터를 가지고 있는 생성자를 사용하여 뷰모델을 생성하는지 알아 보았습니다.

댓글



Designed by JB FACTORY