안드로이드

[Kotlin/Android] ViewModel & ViewModelFactory (뷰모델과 뷰모델팩토리)

란서 2021. 12. 6. 15:01

https://developer.android.com/courses/kotlin-android-fundamentals/overview?hl=ko 

 

Android Kotlin 기초  |  학습 과정  |  Android Developers

Android Kotlin 기초 Android Kotlin 기초 교육 과정은 Google Developers 교육팀에서 만들었습니다. 이 교육 과정에서는 Android Kotlin 프로그래밍 개념에 관해 알아보고 다양한 앱을 빌드합니다. Android Kotlin 기

developer.android.com

 

ViewModel 뷰모델이란?

 

뷰모델 UI 데이터를 저장하고 관리하는 역할을 한다. (단,뷰모델은 자신과 연관된 *UI-Controller의 라이플 사이클에 종속된다.) 

 

*UI-Controller : Fragment와 Activity와 같은 UI-Based Class 를 의미한다. UI 컨트롤러에는 다음과 같은 Logic이 권장된다.

 

  • UI를 다루는 View를 보여주는 로직 
  • OS와 상호작용 하는 로직 (예: 사용자의 Input을 캡쳐, 사용자가 버튼을 누를 때 등등)
  • data를 직접 다루지 않는 로직.

UI-Controller는 Configuraiton Change(구성 변화)가 있을 경우 (화면 전환 등) 모든 변수들이 새롭게 초기화 된다.
 

만약 UI-Controller 내에 UI에 보여질 데이터가 다뤄진다면, 구성 변화가 있을 때마다 데이터가 초기화 되는 문제 발생. 

예를 들어, 어떤 동영상을 세로로 보고 있었는데, 중간쯤에서 가로로 화면 전환(구성 변화)을 하면 다시 처음부터 시작되는 문제가 발생하게 됨.

 

위와 같은 문제를 해결하기 위해서 ViewModel 을 만들어 UI 데이터를 다루고, 해당 뷰모델을 UI 컨트롤러의 생명주기에 종속시켜 뷰모델의 데이터가 보여질 수 있게 하는 역할 을 수행한다.

 

이는 안드로이드 앱 아키텍쳐에서도 권장하는 MVVM 아키텍쳐 유형이다.

 

ViewModel 생성

 

Fragment나 Activity의 Package에 ViewModel class를 만들고 Viewmodel() 추상 클래스를 상속한다.

 

class TestViewModel : Viewmodel() {}

 

  • 뷰모델은 연관된 Fragment가 detached 될 때 또는 Activity가 fininsh 될 때 파괴된다. (파괴 되기 직전 onCleared() 호출)
  • 뷰모델은 UI-Controller와 연결 되어야 한다. 연결되기 위해서 해당 UI 컨트롤러에 reference를 생성한다.
  • 뷰모델 클래스의 객체로 생성된 뷰모델 변수는 UI 컨트롤러의 구성 변화가 있을 때 초기화 될 수 있기 때문에, *ViewModelProvider를 사용하여 뷰모델 변수를 초기화 한다.

    *ViewModelProvider는 뷰모델 객체를 매개변수로 주어진 context의 라이플 사이클과 연관이 있는 뷰모델을 찾고, .get() 함수를 통해 동일한 뷰모델 객체가 있다면 해당 객체를,  없다면 새로온 뷰모델 객체를 return 한다.  

    또한 ViewModelProvider는 UI 컨트롤러의 스코프가 계속 살아있는 한 뷰모델을 계속 보유한다. 따라서 뷰모델의 데이터는 구성 변화에도 불구하고 유지.
//TestFragment or TestActivity

class TestFragment: Fragment() {
	private latient var viewModel : TestViewModel
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
                              
                ..
                
                viewModel = ViewModelProvider(this)[TestViewModel::class.java] //.get(TestViewModel::class.java)
                
                ..
     }

 

ViewModelFactory 뷰모델 팩토리란?

뷰모델 팩토리는 파라미터가 있는 뷰모델을 객체화 시키는 역할을 한다. 이는 UI-컨트롤러끼리 데이터를 주고받으면서 뷰모델에 어떤 인수를 넣어 초기화하고 싶을 때 뷰모델 팩토리를 이용해 초기화한다. 

 

 

ViewModelFactory 생성

 

class TestViewModelFactory(private val value : Int): ViewmodelProvider.Factory{
	//필수
    override fun <T: Viewmodel> create(modelClass: Class<T>):T {
    	if(modelClass.isAssignFrom(TestParameterViewModel::class.java)
        	return TestParameterViewModel(value) as T
    }
    Throw IllegalArgumentException("Unknown viewModel Class")
}

 

class TestParaFragment : Fragment() {
	private latient var viewModel : TestParaViewModel
    private latient var viewModelFactory: TestParaViewModelFactory
    
    override fun onCreateView(inflater: LayoutInflater, container:ViewGroup?, savedInstanceState:Bundle?):View? {
    	..
        
        viewModelFactory = TestParaViewModelFactory(TestParaFragmentArgs.fromBundle(requireArguments()).value
        viewModel = ViewmodelProvider(this, viewModelFactory)[TestParaViewModel::class.java]
        
        ..
    }

}

 

 

정리