如何解决由以下原因引起:java.lang.InstantiationException:类WordViewModel没有零参数构造函数
无法实例化Wordviewmodel 原因:java.lang.InstantiationException:类com.example.roomwordsample.Wordviewmodel没有零参数构造函数
我试图用回收者视图显示房间数据,但无法通过viewmodelProvider get方法实例化类
Wordviewmodel.kt
package com.example.roomwordsample
import android.app.Application
import androidx.lifecycle.Androidviewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewmodelScope
import kotlinx.coroutines.dispatchers
import kotlinx.coroutines.launch
class Wordviewmodel(application: Application) : Androidviewmodel(application) {
private val repository: WordRepository
// Using LiveData and caching what getAlphabetizedWords returns has several benefits:
// - We can put an observer on the data (instead of polling for changes) and only update the
// the UI when the data actually changes.
// - Repository is completely separated from the UI through the viewmodel.
val allWords: LiveData<List<Word>>
init {
val wordsDao = WordRoomDatabase.getDatabase(application,viewmodelScope).wordDao()
repository = WordRepository(wordsDao)
allWords = repository.allWords
}
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insert(word: Word) = viewmodelScope.launch(dispatchers.IO) {
repository.insert(word)
}
}
MainActivity.kt
package com.example.roomwordsample
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.viewmodelProvider
import androidx.recyclerview.widget.linearlayoutmanager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : AppCompatActivity() {
private val newWordActivityRequestCode = 1
private lateinit var wordviewmodel: Wordviewmodel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
val adapter = Wordlistadapter(this)
recyclerView.adapter = adapter
recyclerView.layoutManager = linearlayoutmanager(this)
wordviewmodel = viewmodelProvider(this).get(Wordviewmodel::class.java)
wordviewmodel.allWords.observe(this,Observer { words ->
// Update the cached copy of the words in the adapter.
words?.let { adapter.setWords(it) }
})
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setonClickListener {
val intent = Intent(this@MainActivity,NewWordActivity::class.java)
startActivityForResult(intent,newWordActivityRequestCode)
}
}
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if (requestCode == newWordActivityRequestCode && resultCode == Activity.RESULT_OK) {
data?.getStringExtra(NewWordActivity.EXTRA_REPLY)?.let {
val word = Word(it)
wordviewmodel.insert(word)
}
} else {
Toast.makeText(
applicationContext,R.string.empty_not_saved,Toast.LENGTH_LONG).show()
}
}
}
解决方法
尝试将视图模型工厂添加到您的视图模型类中。
package com.example.roomwordsample
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class WordViewModel(application: Application) : AndroidViewModel(application) {
private val repository: WordRepository
// Using LiveData and caching what getAlphabetizedWords returns has several benefits:
// - We can put an observer on the data (instead of polling for changes) and only update the
// the UI when the data actually changes.
// - Repository is completely separated from the UI through the ViewModel.
val allWords: LiveData<List<Word>>
init {
val wordsDao = WordRoomDatabase.getDatabase(application,viewModelScope).wordDao()
repository = WordRepository(wordsDao)
allWords = repository.allWords
}
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insert(word: Word) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(word)
}
class Factory(
private val app: Application
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(WordViewModel::class.java)) {
return WordViewModel(app) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
}
然后在MainActivity中像这样初始化视图模型:
package com.example.roomwordsample
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : AppCompatActivity() {
private val newWordActivityRequestCode = 1
private val wordViewModel by viewModels<WordViewModel> {
WordViewModel.Factory(application)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
val adapter = WordListAdapter(this)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
//wordViewModel = ViewModelProvider(this).get(WordViewModel::class.java)
wordViewModel.allWords.observe(this,Observer { words ->
// Update the cached copy of the words in the adapter.
words?.let { adapter.setWords(it) }
})
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
val intent = Intent(this@MainActivity,NewWordActivity::class.java)
startActivityForResult(intent,newWordActivityRequestCode)
}
}
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if (requestCode == newWordActivityRequestCode && resultCode == Activity.RESULT_OK) {
data?.getStringExtra(NewWordActivity.EXTRA_REPLY)?.let {
val word = Word(it)
wordViewModel.insert(word)
}
} else {
Toast.makeText(
applicationContext,R.string.empty_not_saved,Toast.LENGTH_LONG).show()
}
}
}
,
我通过以下方式解决了这个问题
wordViewModel = ViewModelProvider(this).get(WordViewModel::class.java)
以此更改上面的代码:
wordViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(WordViewModel::class.java)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。