프로그래밍/Android

[Android] IllegalStateException: Method addObserver must be called on the main thread

Lou Park 2022. 7. 17. 12:12

문제발생

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]
}