java.lang.RuntimeException: 无法创建 class ViewModel 的实例
java.lang.RuntimeException: Cannot create an instance of class ViewModel
我正在尝试实例化一个 viewModel
class,其中包含一个 init 块,我试图在其中发送带有截击的 Get 请求。问题是当我试图在我的 Fragment class 中实例化这个 class 时,我收到了这个错误,我不知道为什么。也许来自构造函数的上下文是问题所在?感谢:
视图模型class
class BooksFragmentViewModel(c : Context) : ViewModel() {
lateinit var cont: Context
var books: MutableLiveData<MutableList<BookItem>> = MutableLiveData<MutableList<BookItem>>()
var triggerAddBook = MutableLiveData<Boolean>()
var triggerDeleteBook = MutableLiveData<Boolean>()
var triggerEditBook = MutableLiveData<Boolean>()
var bookRepo: BookRepository = BookRepository()
var bookItemAdd: BookItem? = null
var bookItemDelete: BookItem? = null
var bookItemEdit : BookItem? = null
var bookNew: LiveData<BookItem> = Transformations.switchMap(triggerAddBook) {
if (it != null && it)
addBook()
else
null
}
init {
books = bookRepo.booksGetRequest(c)
}
片段Class
class BooksFragment : Fragment(), BooksAdapter.OnDeleteBtnClicked, BooksAdapter.OnEditBtnClicked {
lateinit var booksModel: BooksFragmentViewModel
var position: Int = 0
private var adapter: BooksAdapter = BooksAdapter(this, this)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_books, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
booksModel = ViewModelProvider(requireActivity()).get(BooksFragmentViewModel::class.java)
booksLoading_progressBar.visibility = View.VISIBLE
var c: Context? = context
if (c != null) {
booksModel.setContext(c)
}
如果你有一个带参数的 ViewModel
(比如你的例子中的上下文),那么你需要使用 Factory
将任何参数传递给那个 ViewModel
booksModel = ViewModelProvider(this,object :
ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return booksModel(requireActivity()) as T
}
}).get(booksModel::class.java)
问题确实是因为带参数的主构造函数。您要求 ViewModelProvider
创建 BooksFragmentViewModel
class 的实例,但提供者对预期参数一无所知。
Here is a post 关于那个主题。
如何解决这个问题?
- 如果可能,删除所有主构造函数参数。这应该是最简单的方法;
- 创建
ViewModelProvider.Factory
来处理视图模型的创建。
第一个选项很明确,但对于第二个选项,您应该执行以下操作。
创建 ViewModelProvider.Factory
:
class BooksFragmentViewModelFactory (val context: Context) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(BooksFragmentViewModel::class.java)) {
return BooksFragmentViewModel(context) as T
} else {
throw RuntimeException("Failed to create instance of the ${modelClass.simpleName}")
}
}
}
将工厂与 ViewModelProvider
一起使用:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val bookViewModelFactory = BooksFragmentViewModelFactory(requireContext())
booksModel = ViewModelProvider(requireActivity(), bookViewModelFactory).get(BooksFragmentViewModel::class.java)
booksLoading_progressBar.visibility = View.VISIBLE
}
有关更多说明,请查看此 codelab from Google (step 8)。有足够的示例来了解如何使用视图模型工厂的基础知识。
我正在尝试实例化一个 viewModel
class,其中包含一个 init 块,我试图在其中发送带有截击的 Get 请求。问题是当我试图在我的 Fragment class 中实例化这个 class 时,我收到了这个错误,我不知道为什么。也许来自构造函数的上下文是问题所在?感谢:
视图模型class
class BooksFragmentViewModel(c : Context) : ViewModel() {
lateinit var cont: Context
var books: MutableLiveData<MutableList<BookItem>> = MutableLiveData<MutableList<BookItem>>()
var triggerAddBook = MutableLiveData<Boolean>()
var triggerDeleteBook = MutableLiveData<Boolean>()
var triggerEditBook = MutableLiveData<Boolean>()
var bookRepo: BookRepository = BookRepository()
var bookItemAdd: BookItem? = null
var bookItemDelete: BookItem? = null
var bookItemEdit : BookItem? = null
var bookNew: LiveData<BookItem> = Transformations.switchMap(triggerAddBook) {
if (it != null && it)
addBook()
else
null
}
init {
books = bookRepo.booksGetRequest(c)
}
片段Class
class BooksFragment : Fragment(), BooksAdapter.OnDeleteBtnClicked, BooksAdapter.OnEditBtnClicked {
lateinit var booksModel: BooksFragmentViewModel
var position: Int = 0
private var adapter: BooksAdapter = BooksAdapter(this, this)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_books, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
booksModel = ViewModelProvider(requireActivity()).get(BooksFragmentViewModel::class.java)
booksLoading_progressBar.visibility = View.VISIBLE
var c: Context? = context
if (c != null) {
booksModel.setContext(c)
}
如果你有一个带参数的 ViewModel
(比如你的例子中的上下文),那么你需要使用 Factory
将任何参数传递给那个 ViewModel
booksModel = ViewModelProvider(this,object :
ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return booksModel(requireActivity()) as T
}
}).get(booksModel::class.java)
问题确实是因为带参数的主构造函数。您要求 ViewModelProvider
创建 BooksFragmentViewModel
class 的实例,但提供者对预期参数一无所知。
Here is a post 关于那个主题。
如何解决这个问题?
- 如果可能,删除所有主构造函数参数。这应该是最简单的方法;
- 创建
ViewModelProvider.Factory
来处理视图模型的创建。
第一个选项很明确,但对于第二个选项,您应该执行以下操作。
创建 ViewModelProvider.Factory
:
class BooksFragmentViewModelFactory (val context: Context) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(BooksFragmentViewModel::class.java)) {
return BooksFragmentViewModel(context) as T
} else {
throw RuntimeException("Failed to create instance of the ${modelClass.simpleName}")
}
}
}
将工厂与 ViewModelProvider
一起使用:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val bookViewModelFactory = BooksFragmentViewModelFactory(requireContext())
booksModel = ViewModelProvider(requireActivity(), bookViewModelFactory).get(BooksFragmentViewModel::class.java)
booksLoading_progressBar.visibility = View.VISIBLE
}
有关更多说明,请查看此 codelab from Google (step 8)。有足够的示例来了解如何使用视图模型工厂的基础知识。