我只是试着按照本指南来了解MVVM体系结构:https://developer.android.com/jetpack/guide
我的问题是:当我在ViewModel类中使用两个参数时"SavedStateHangle";以及";UserRepository";,然后我的应用程序崩溃,出现以下错误:
E/AndroidRuntime:在android.app.servertransaction.LaunchActivityItem.exexecute(LaunchActivityItem.java:78)在android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)在android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)在android.app.ActivityThread$H.handleMessage(ActivityThreads.java:1955)在android.os.Handler.dispatchMessage(Handler.java:106)在android.os.Looper.loop(Looper.java:214)在android.app.ActivityThread.main(ActivityThreads.java:7058)位于java.lang.reflect.Method.ioke(本机方法)网址:com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)网址:com.android.internal.os.ZygoteInit.main(ZygoteNit.java:965)引起原因:java.lang.InstructionException:java.lang.Class<ru.itschool.jetpackguide.UserProfileViewModel>在java.lang.Class.newInstance(Native Method)中没有零参数构造函数在androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
如果我从构造函数参数中删除UserRepository(并且构造函数只有SavedStateHandle),那么片段就可以工作(没有UserRepository,但它不会因此错误而崩溃)。
我将ViewModel与SavedStateViewModelFactory和Hilt+Dagger库一起使用,就像Android应用程序体系结构指南中一样。
我在UserProfileFragment:上用这段代码创建我的ViewModel
private val viewModel : UserProfileViewModel
by viewModels(
factoryProducer = {SavedStateViewModelFactory(activity?.application, this, defaultBundle())}
)
和我的ViewModel代码:
@HiltViewModel
class UserProfileViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
userRepository: UserRepository
) : ViewModel() {
var userId: String = savedStateHandle["uid"]
?: throw IllegalArgumentException("Missing user ID")
private val _user = MutableLiveData<User>()
val user : LiveData<User> = _user
init {
viewModelScope.launch {
_user.value = userRepository.getUser(userId)
}
}
}
你可以在这里找到我项目的完整代码。也许有人在我之前实施了这个指南,并且已经知道答案了?:)
当您为ViewModel
提供工厂时,如果ViewModel
的实例还不存在,则为viewModels
提供了一种创建实例的方法。SavedStateViewModelFactory
只提供了一种用SavedStateHandle
实例化ViewModel
的方法,如果没有您的一些工作,它显然不知道如何提供自定义存储库。
因此,为了给它所需的帮助,您可能应该考虑创建ViewModelProvider.Factory
的自定义实现,这需要您实现create
方法:
class VMF: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {}
}
对于您的示例,假设您想要ViewModel
中可用的片段参数,简化的实现将是:
class VMF(private val userRepository: UserRepository, private val args: Bundle?): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(UserProfileViewModel::class.java.isAssignableFrom(modelClass)) {
return UserProfileViewModel(userRepository, args)
}
...
}
}
然后你会用你的工厂来代替默认的工厂:
private val viewModel : UserProfileViewModel by viewModels {
VMF(userRepository, arguments)
}
尽管这个答案并不完全适用于@Eldar Kurbanov的情况?你们中的任何人可能只是忘记了视图模型上方的@HiltViewModel
注释。