새 프로젝트에서 ViewModel 클래스의 인스턴스를 만들 수 없습니다.

Nov 25 2020

두 가지 다른 프로젝트가 있습니다. 첫 번째에서는 내 활동 및 Room 데이터베이스와 함께 ViewModel을 사용합니다. 모든 것이 작동합니다. 그런 다음 다른 목적으로 새 프로젝트를 만들었고 ViewModel을 완전히 동일한 방식으로 인스턴스화했지만 내 앱이 다음 오류와 함께 충돌합니다.

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.MainViewModel
    at android.app.ActivityThread.performLaunchActivity(Unknown Source:591)
    at android.app.ActivityThread.handleLaunchActivity(Unknown Source:36)
    at android.app.servertransaction.LaunchActivityItem.execute(Unknown Source:57)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(Unknown Source:99)
    at android.app.servertransaction.TransactionExecutor.execute(Unknown Source:34)
    at android.app.ActivityThread$H.handleMessage(Unknown Source:36) at android.os.Handler.dispatchMessage(Unknown Source:21) at android.os.Looper.loop(Unknown Source:207) at android.app.ActivityThread.main(Unknown Source:107) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(Unknown Source:11)
    at com.android.internal.os.ZygoteInit.main(Unknown Source:274)
 Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.MainViewModel
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) at com.kazguiu.MainActivity.applyAdapterAndViewModel(MainActivity.kt:37) at com.kazguiu.MainActivity.onCreate(MainActivity.kt:25) at android.app.Activity.performCreate(Unknown Source:16) at android.app.Activity.performCreate(Unknown Source:1) at android.app.Instrumentation.callActivityOnCreate(Unknown Source:3) at android.app.ActivityThread.performLaunchActivity(Unknown Source:368) at android.app.ActivityThread.handleLaunchActivity(Unknown Source:36)  at android.app.servertransaction.LaunchActivityItem.execute(Unknown Source:57)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(Unknown Source:99)  at android.app.servertransaction.TransactionExecutor.execute(Unknown Source:34)  at android.app.ActivityThread$H.handleMessage(Unknown Source:36) 
    at android.os.Handler.dispatchMessage(Unknown Source:21) 
    at android.os.Looper.loop(Unknown Source:207) 
    at android.app.ActivityThread.main(Unknown Source:107) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(Unknown Source:11)  at com.android.internal.os.ZygoteInit.main(Unknown Source:274)  Caused by: java.lang.InstantiationException: java.lang.Class<com.example.MainViewModel> has no zero argument constructor at java.lang.Class.newInstance(Native Method) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)

다음과 같은 활동에서 ViewModel을 인스턴스화합니다.

private lateinit var mainViewModel: MainViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    applyAdapterAndViewModel()

}

private fun applyAdapterAndViewModel() {
    mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
}

내 ViewModel :

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val exampleDao = Database.getDatabase(application).exampleDao()
    private val repository = Repository(exampleDao)

    fun getSubjects() = repository.getSubjects()

    fun addSubjects(subject: Subjects) = viewModelScope.launch(Dispatchers.IO) {
        repository.addSubject(subject)
    }

}

ViewModel을 사용하는이 방법은 이전 프로젝트와 동일합니다. 유일한 차이점은 현재 gradle에 두 가지 추가 종속성이 있다는 것입니다.

implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

삭제하면 Android Studio는 ViewModelProvider를 인식하지 못하지만 이전 프로젝트에는 이러한 종속성이 전혀 없으며 LiveData와 ViewModel을 절대적으로 동일한 방식으로 사용합니다 (가져 오기도 동일). 그래서 나는 무엇을해야합니까?

답변

1 AndrewChelix Nov 25 2020 at 11:52

ViewModel에는 다음과 같이 ViewModelFactory를 사용해야 application: Application만 제공 할 수 있는 인수 가 필요합니다 .

ViewModelFactory

class MainViewModelFactory(
    private val application: Application
) : ViewModelProvider.Factory {
    @Suppress("unchecked_cast")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            return MainViewModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

주요 활동

private fun applyAdapterAndViewModel() {
// Not so kotlinic
mainViewModel = ViewModelProvider(this,MainViewModelFactory(application)).get(MainViewModel::class.java)
}

또한, MainActivity에 교체 private lateinit var mainViewModel: MainViewModel

private val viewModel by viewModels<MainViewModel> { 
MainViewModelFactory(application) }