문제발생
IllegalStateException: Method addObserver must be called on the main thread
ViewModel을 가지고 뭔가 하려했을때 해당 오류가 발생하는 경우가 있다. 이것은 ViewModel을 lazy init해서 사용할 시에 발생하게 되는데, 나의 경우에는 아래와 같은 코드에서 발생했다.
private val splashViewModel by viewModels<SplashViewModel>()
override fun onStart() {
super.onStart()
lifecycleScope.launch(Dispatchers.IO) {
splashViewModel.doSomething()
}
}
원인
처음에는 "무슨 소리야 옵저버같은거 안붙였는데"라고 반발이 올라왔지만, 컴퓨터는 틀리지 않는다...사람이 틀리는거지라며 오늘도 코드를 보며 수긍한다. viewModels<>()를 까보면 이렇게 생겼음을 알 수 있는데, Annotation에도 노트되어있듯이 MainThread에서 불려져야한다. lazy init은 해당 객체가 처음 불릴때 수행되므로, 내 코드에서는 외부스레드에서 viewModel을 호출했으니 오류가 떴던 것이다.
@MainThread
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}
해결방법
작업 이전에 ViewModel을 초기화 시켜주면 된다. Application에 Activity가 붙기전에 초기화시키면 IllegalArgumentException을 발생시킬 수 있으니 주의하자.
private lateinit var splashViewModel: SplashViewModel
fun onStart() {
splashViewModel = ViewModelProvider(this)[SplashViewModel::class.java]
}
'프로그래밍 > Android' 카테고리의 다른 글
[Bitrise Cli] 리눅스 서버에서 CI/CD pipeline 직접 구축해보기 (1) (0) | 2022.07.27 |
---|---|
[Android] 진짜 쉬운 Main Thread와 Handler (0) | 2022.07.18 |
Bitrise에서 버전명(혹은 버전코드) 환경변수로 사용하기 (0) | 2022.07.13 |
[안드로이드] Airbnb Epoxy 라이브러리 놓치기 쉬운 부분들 (0) | 2022.05.23 |
Upstream Flow, Downstream Flow (0) | 2022.05.20 |