ViewModel에서 Context?
간단한 메모 앱을 만들다가 ViewModel에서 Room 데이터베이스의 인스턴스를 생성할 때 context를 사용해야하는 문제가 발생하였습니다.
하지만 ViewModel에서는 activity context를 참조하면 안되기 때문에 context를 액티비티나 프래그먼트에서 사용하는 것처럼 간단하게 사용할 수 없습니다.
방법1, ViewModel이 아닌 AndroidViewModel을 상속 받기
ViewModel 클래스가 ViewModel 클래스가 아닌 Application 클래스를 기본상속자로 가지는 AndroidViewModel 클래스
를 상속받으면 됩니다.
context를 사용할 때는 application
을 직접 사용하거나 application.appplicationContext
로 사용할 수 있습니다. application
을 직접 사용할 수있는 이유는 Application 클래스
가 Context 클래스
가 확장된 클래스
이기 때문입니다.
class MemoViewModel(application: Application) : AndroidViewModel(application) {
... 생략 ...
init {
// application 또는 application.appplicationContext으로 사용
val memoDAO = MemoDatabase.getInstance(application)!!.memoDAO()
}
}
방법2, 전역 context 사용하기
Application 클래스를 상속받는 별도의 클래스를 만들어 전역 context
를 사용하는 방법도 가능합니다.
class App: Application() {
// context를 singleton으로 생성
companion object {
lateinit var instance: App
private set
fun context() : Context {
return instance.applicationContext
}
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
위와 같은 클래스를 만들어준 후 AndroidManifest
파일의 <application>
에 android:name=".App"
을 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".App"
... 생략 ...
>
이렇게 설정해주면 ViewModel에서 App.instance
나 App.context()
를 통해 context를 사용할 수 있습니다.
class MemoViewModel :ViewModel() {
... 생략 ...
init {
// App.context()를 통해 context 사용
val memoDAO = MemoDatabase.getInstance(App.context())!!.memoDAO()
}
}
App.instance
를 통해 바로 context를 사용할 수 있는 이유
는 위에서 살펴본 것과 같이 insteance가 App 클래스
자료형을 가지는데, App 클래스
는 Application 클래스
를 상속 받고, Application 클래스
는 Context 클래스
가 확장된 클래스
이기 때문입니다.