저번 시간에 ViewModel에 대해 알아보았는데요,
이전 시간 게시글을 보지 못한 분들을 위해
아래에 이전 시간에 작성한 게시글 링크를 달아놓겠습니다.
https://minhyuuk.tistory.com/6
일반적으로 ViewModel을 만들어 사용하는 건 매우 간단합니다.
하지만 생성자나 매개 변수를 사용하지 않고
ViewModel 개체를 인스턴스화 하여
생성하는 경우에는 어떻게 해야 할까요?
그럴 때 ViewModelFactory를 사용합니다.
ViewModelFactory는 생성자 매개 변수를 사용하거나 사용하지 않고, ViewModel 개체를 인스턴스화 합니다.
즉, ViewModelFactory는 ViewModel을 통해 전달되는 인자가 있을 때 사용됩니다.
그럼 이제 ViewModelFactory를 한 번 사용해볼까요?
MainActivityViewModel.kt
package com.app.databinding
import androidx.lifecycle.ViewModel
class MainActivityViewModel(startingTotal : Int) : ViewModel() {
private var total = 0
// init을 통해 startingTotal을 total로 할당
init {
total = startingTotal
}
// 결과값을 return 하는 함수
fun getTotal(): Int{
return total
}
// 숫자를 더할 때 사용할 함수
fun setTotal(input : Int){
total += input
}
}
하지만 이전에 해야 할 일이 있습니다.
전 시간에 작성한 코드입니다.
전달할 인자인 startingTotal을 선언합니다.
ViewModelFactory에 ViewModel의 인자를 검사할 겁니다.
어떻게 검사하는지 ViewModel Factory를 살펴볼까요?
MainActivityViewModelFactory.kt
package com.app.databinding
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import java.lang.IllegalArgumentException
class MainActivityViewModelFactory(private val startingTotal : Int) : ViewModelProvider.Factory {
// ViewModelProvider.Factory를 확장함.
// 오버라이드 하면 아래와 같은 create 함수를 받을 수 있음.
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
// modelClass에 MainActivityViewModel이 상속이 되었나요? 라고 물어봅니다.
if(modelClass.isAssignableFrom(MainActivityViewModel::class.java)){
// 맞다면 MainViewModel의 파라미터 값을 넘겨주죠.
return MainActivityViewModel(startingTotal = startingTotal) as T
}
// 상속이 되지 않았다면 IllegalArgumentException을 통해 상속이 되지 않았다는 에러를 띄웁니다.
throw IllegalArgumentException("Unknown ViewModel Class")
}
}
MainActivityViewModelFactory 클래스에 ViewModelProvider.Factory를 확장합니다.
그 후 메서드를 오버 라이딩합니다.
if문을 통해 MainActivityViewModelFactory 클래스가 상속되었는지 묻고
맞다면 MainViewModel의 파라미터 값을 넘겨줍니다.
그렇지 않다면 상속이 되지 않았다는 에러를 검출합니다.
MainActivity.kt
package com.app.databinding
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.app.databinding.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
// 나중에 정의한 변수들을 lateinit var로 선언
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainActivityViewModel
private lateinit var viewModelFactory: MainActivityViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// databinding 적용.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// 시작 값을 100으로 지정
viewModelFactory = MainActivityViewModelFactory(startingTotal = 100)
// viewModel의 주최를 MainActivityViewModel, owner에 viewModelFactory도 추가
viewModel = ViewModelProvider(this,viewModelFactory).get(MainActivityViewModel::class.java)
// getTotal()를 호출해 현재 total(현재 값 : 0)을 불러온다.
binding.textSum.text = viewModel.getTotal().toString()
binding.buttonCount.setOnClickListener {
// setTotal()을 호출해 edittext의 값을 total에 더한다.
viewModel.setTotal(binding.countEditText.text.toString().toInt())
// 현재 값을 불러온다.
binding.textSum.text = viewModel.getTotal().toString()
}
}
}
이제 ViewModelFactory를 사용해야겠죠.
MainActivity는 추가된 코드가 별로 없습니다.
viewModelFactory를 선언합니다. owner에도 추가해주세용.
viewModelFactory = MainActivityViewModelFactory(startingTotal = 100)
-> 시작 값을 100으로 지정합니다.
그럼 이제 시작 값이 100부터 시작하는 덧셈을 하실 수 있습니다.
실행 화면 보실까요?
와우! 시작 값이 100이네요.
어플이 잘 동작합니다.
위의 ViewModelFactory는 기본이 되는 ViewModelFactory입니다.
응용하실 때 위의 코드를 베이스로 하여 응용하시면 좋을 거 같습니다.
이 글을 마치며
ViewModel에 이어 ViewModelFactory까지 사용해보았는데요,
다음 시간에는 응용이 가능한 LiveData에 대해 알아보도록 하겠습니다.
참고
https://dduntorry.tistory.com/entry/Android-ViewModelFactory
'Android > Kotlin' 카테고리의 다른 글
[Android/Kotlin] LiveData에 대해 알아보자! (0) | 2022.04.26 |
---|---|
[Android/Kotlin] RecyclerView에 대해 알아보자! (0) | 2022.03.26 |
[Android/Kotlin] Intent를 사용하자! (0) | 2022.03.25 |
[Android/Kotlin] Collection에 대해 알아보자 (0) | 2022.03.22 |