Android ViewModel 没有零参数构造函数
Android ViewModel has no zero argument constructor
我正在关注 this 文档以了解 LiveData 和 ViewModel。
在文档中,ViewModel class 具有构造函数,
public class UserModel extends ViewModel {
private MutableLiveData<User> user;
@Inject UserModel(MutableLiveData<User> user) {
this.user = user;
}
public void init() {
if (this.user != null) {
return;
}
this.user = new MutableLiveData<>();
}
public MutableLiveData<User> getUser() {
return user;
}
}
但是,当我 运行 代码时,出现异常:
final UserViewModelviewModel = ViewModelProviders.of(this).get(UserViewModel.class);
Caused by: java.lang.RuntimeException: Cannot create an instance of class UserViewModel
Caused by: java.lang.InstantiationException:
java.lang.Class
has no zero argument constructor
在使用 ViewModelProviders
初始化 ViewModel
的子 class 时,默认情况下它希望您的 UserModel
class 具有零参数构造函数。
在您的情况下,您的构造函数具有参数 MutableLiveData<User> user
.
解决此问题的一种方法是为您的 UserModel
.
使用默认的无参数构造函数
否则,如果您想为您的 ViewModel class 使用非零参数构造函数,您可能必须创建自定义 ViewModelFactory
class 来初始化您的 ViewModel 实例,它实现了 ViewModelProvider.Factory
接口。
我还没有尝试过,但是这里有一个 link 到一个优秀的 Google 示例:github.com/googlesamples/android-architecture-components。
具体来说,查看此 class GithubViewModelFactory.java for Java code and this class GithubViewModelFactory.kt 以获取相应的 Kotlin 代码。
ViewModelFactory
这将为我们提供来自 ViewModelModule
的正确 ViewModel
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels;
@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels) {
this.viewModels = viewModels;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
Provider<ViewModel> viewModelProvider = viewModels.get(modelClass);
if (viewModelProvider == null) {
throw new IllegalArgumentException("model class " + modelClass + " not found");
}
return (T) viewModelProvider.get();
}
}
ViewModelModule
负责将整个 ViewModel 类 绑定到
Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);
//You are able to declare ViewModelProvider.Factory dependency in another module. For example in ApplicationModule.
@Binds
@IntoMap
@ViewModelKey(UserViewModel.class)
abstract ViewModel userViewModel(UserViewModel userViewModel);
//Others ViewModels
}
ViewModelKey
是在地图中用作键的注释,看起来像
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
Class<? extends ViewModel> value();
}
现在您可以创建 ViewModel 并满足图中所有必要的依赖关系
public class UserViewModel extends ViewModel {
private UserFacade userFacade;
@Inject
public UserViewModel(UserFacade userFacade) { // UserFacade should be defined in one of dagger modules
this.userFacade = userFacade;
}
}
实例化 ViewModel
public class MainActivity extends AppCompatActivity {
@Inject
ViewModelFactory viewModelFactory;
UserViewModel userViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getAppComponent().inject(this);
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);
}
}
并且不要伪造将 ViewModelModule
添加到 modules
列表中
@Singleton
@Component(modules = {ApplicationModule.class, ViewModelModule.class})
public interface ApplicationComponent {
//
}
如果构造函数中有参数,则:
DAGGER 2 public @inject 依赖的构造函数
@Inject
public UserViewModel(UserFacade userFacade)
{
this.userFacade = userFacade;
}
否则dagger 2会给你报错"can not instantiate viewmodel object"
问题可以通过从 AndroidViewModel
扩展 UserModel
来解决,后者是应用程序上下文感知 ViewModel 并且需要 Application
仅参数构造函数。 (documentation)
Ex-(在科特林中)
class MyVm(application: Application) : AndroidViewModel(application)
这适用于版本 2.0.0-alpha1
。
我编写了一个库,它应该可以更直接、更清晰地实现这一点,不需要多重绑定或工厂样板,同时还可以在运行时进一步参数化 ViewModel
:
https://github.com/radutopor/ViewModelFactory
@ViewModelFactory
class UserViewModel(@Provided repository: Repository, userId: Int) : ViewModel() {
val greeting = MutableLiveData<String>()
init {
val user = repository.getUser(userId)
greeting.value = "Hello, $user.name"
}
}
在视图中:
class UserActivity : AppCompatActivity() {
@Inject
lateinit var userViewModelFactory2: UserViewModelFactory2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
appComponent.inject(this)
val userId = intent.getIntExtra("USER_ID", -1)
val viewModel = ViewModelProviders.of(this, userViewModelFactory2.create(userId))
.get(UserViewModel::class.java)
viewModel.greeting.observe(this, Observer { greetingText ->
greetingTextView.text = greetingText
})
}
}
2020 年初,Google 在 androidx 生命周期库的 2.2.0 版中弃用了 ViewModelProviders class。
不再需要使用 ViewModelProviders 来创建 ViewModel 的实例,您可以将 Fragment 或 Activity 实例传递给 ViewModelProvider 构造函数。
如果您使用如下代码:
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
您会收到一条警告,指出 ViewModelProviders 已被弃用。
您可以改为:
val viewModel = ViewModelProvider(this).get(CalculatorViewModel::class.java)
或者,要使用委托,请进行以下更改。
在build.gradle(Module:app)文件中,使用2.2.0版本的lifecycle
组件:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
另加
implementation "androidx.activity:activity-ktx:1.1.0"
如果您想使用 Fragment 中的 ViewModel,请使用
implementation "androidx.fragment:fragment-ktx:1.2.2"
fragment-ktx 自动包含 activity-ktx,所以你不需要
在依赖项中指定两者。
您需要在 android 部分指定 Java 8 :
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.kgandroid.calculator"
minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
kotlinOptions {
jvmTarget = "1.8"
}
}
在您的 Fragment 或 Activity 中,将导入更改为:
导入androidx.activity.viewModels
创建 ViewModel 的代码变为:
val viewModel: CalculatorViewModel by viewModels()
而不是
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
使用 viewModel 对象作为 :
val viewModel:viewModels() 的 CalculatorViewModel
viewModel.newNumber.observe(this, Observer { stringResult ->
newNumber.setText(stringResult) })
其中 newNumer 是一个 LiveData 对象
In a Fragment that you want to share the Activity's ViewModel, you'd use
`val viewModel: CalculatorViewModel by activityViewModels()`
**That's the equivalent of passing the Activity instance in the (deprecated)
ViewModelProviders.of() function.**
创建一个不带任何参数的构造函数,即
Default/ No-arg constructor
在视图模型中 class .
在我的例子中,我忘记生成这个构造函数并在我学习时浪费了 30 分钟 - 之后它对我有用。
遇到这个问题的各位,我是这样遇到的:
1- 在您的 ViewModel 中,不要 创建构造函数,只需创建一个接受上下文和其他参数的函数
public class UserModel extends ViewModel {
private Context context;
private ..........;
public void init(Context context, ......) {
this.context = context;
this..... = ....;
}
// Your stuff
}
2- 在你的 activity:
UserViewModel viewModel = ViewModelProviders.of(this).get(UserViewModel.class);
viewModel.init(this, .....);
// You can use viewModel as you want
3- 在你的片段中
UserViewModel viewModel = ViewModelProviders.of(getActivity()).get(UserViewModel.class);
viewModel.init(getContext(), .....);
// You can use viewModel as you want
您可以通过视图模型工厂在视图模型中传递数据。您也可以查看this example以供参考。
class UserViewModelFactory(private val context: Context) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return UserViewModel(context) as T
}
}
class UserViewModel(private val context: Context) : ViewModel() {
private var listData = MutableLiveData<ArrayList<User>>()
init{
val userRepository : UserRepository by lazy {
UserRepository
}
if(context.isInternetAvailable()) {
listData = userRepository.getMutableLiveData(context)
}
}
fun getData() : MutableLiveData<ArrayList<User>>{
return listData
}
}
您可以在 activity 中调用视图模型,如下所示。
val userViewModel = ViewModelProviders.of(this,UserViewModelFactory(this)).get(UserViewModel::class.java)
我有同样的问题,通过将导航 ui 库添加到我的项目来修复它:
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
在我使用 HILT 的情况下,它在具有 ViewModel 的片段上方缺少一个注释:@AndroidEntryPoint
@AndroidEntryPoint
class BestFragment : Fragment() {
....
当然在您的 ViewModel class 您还需要使用 Annotate
HILT 需要什么:@ViewModelInject
class BestFragmentViewModel @ViewModelInject constructor(var userManager: UserManager) : ViewModel() {
....
}
2020-07-29 10:13:25
对于 lifecycle_version = '2.2.0'
ViewProviders.of API 已弃用。这是我的情况 :
class MainActivityViewModel(application: Application) : AndroidViewModel(application) {
private var repository: UserRepository
val allUsers: LiveData<List<User>>
......
error:
val userViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
success:
val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application)
userViewModel = ViewModelProvider(this,factory).get(MainActivityViewModel::class.java)
通过 application
api ViewModelProvider.AndroidViewModelFactory.getInstance
关于 ,如果您使用的是 Hilt 并且刚刚添加了 ViewModel,请不要忘记重建您的项目。只是 运行 项目不会创建所需的工厂 类(应该是自动生成的),这是通过艰难的方式发现的。
重建前不存在下面的类:
我有同样的错误。我正在使用 Hilt,在我的例子中,它缺少第二个 hilt 编译器依赖项
现在我有两个:
kapt com.google.dagger:hilt-android-compiler:#version
和
kapt androidx.hilt:hilt-compiler:#version
在我的应用级别 build.gradle 文件中,它有效。
com.google.dagger:hilt-android-compiler 在您使用 Hilt Android Gradle 插件时需要(参见 docs) 和 androidx.hilt:hilt-compiler:#version
当您想要集成 Hilt 和 Jetpack 时显然需要它,例如注入 Android Jetpack ViewModel(参见 docs)
如果您使用 hilt,您可能会忘记使用 @AndroidEntryPoint[ 注释您的 activity 或片段=10=]
我在使用 @ViewModelInject
时遇到了一些问题,因为它已被 HILT 弃用。
要解决此问题,请更改此代码:
class MainViewModel @ViewModelInject constructor(
val mainRepository: MainRepository
): ViewModel()
与:
@HiltViewModel
class MainViewModel @Inject constructor(
val mainRepository: MainRepository
): ViewModel()
当然,请记住在您的片段或 activity 上方添加 @AndroidEntryPoint
注释(无论您在哪里实例化 ViewModel
),如下所示:
@AndroidEntryPoint
class UsageFragment : Fragment(R.layout.fragment_usage) {
.
.
.
}
终极提示:
您可以立即查看 HILT 是否正常工作 查看 ViewModel
左侧是否有图标。
这里不行:
这里 它确实有效:
如果您在更新代码后没有看到它们,请单击 Build -> Rebuild Project
对于 Koin:
我遇到了这个问题,原来我只是从 AndroidX 导入了 viewModels() 而不是从 Koin
导入了 viewModel()
此失败的最常见原因是 Fragment/Activity 开头缺少 @AndroidEntryPoint,如下所示:
@AndroidEntryPoint
class MyFragment : Fragment {
val viewModel by viewModels<MyViewModel>()
}
同样,您的 ViewModel 应由 HiltViewModel 注释,如下所示:
@HiltViewModel
class MyViewModel@Inject constructor(
private val var1: Type1
) : ViewModel()
如果您使用导航组合并在 NavHost 块内调用您的屏幕,则刀柄无法注入视图模型。为此,您可以使用这种方式;
NavHost(navHostController, startDestination = "HomeScreen") {
composable("HomeScreen") {
HomeScreen(homeScreenViewModel = hiltViewModel())
}
}
不要忘记为 hiltViewModel()
添加此依赖项 -> implementation("androidx.hilt:hilt-navigation-compose:1.0.0-alpha02")
如果您使用的是匕首柄和 2.31 或更高版本,则不要在视图模型中使用“ViewModelInject”class。 Dagger 正在提供使用 viewmodel 的新方法,因此请按照以下说明进行操作。
1:在 class 之上添加 @HiltViewModel
2: 使用 Inject intead of ViewModelInject
@HiltViewModel
class AuthViewModel @Inject constructor(
private val authRepository: AuthRepository,
...
) : ViewModel()
{...}
对于刀柄:
为主要活动和片段简单添加 @AndroidEntryPoint
,为视图模型添加 @HiltViewModel
之后的示例:
@HiltViewModel
class SplashViewModel @Inject constructor(
@AndroidEntryPoint
class SplashFragment : Fragment() {
private lateinit var b: SplashFragmentBinding
private val vm: SplashViewModel by viewModels()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
我正在关注 this 文档以了解 LiveData 和 ViewModel。 在文档中,ViewModel class 具有构造函数,
public class UserModel extends ViewModel {
private MutableLiveData<User> user;
@Inject UserModel(MutableLiveData<User> user) {
this.user = user;
}
public void init() {
if (this.user != null) {
return;
}
this.user = new MutableLiveData<>();
}
public MutableLiveData<User> getUser() {
return user;
}
}
但是,当我 运行 代码时,出现异常:
final UserViewModelviewModel = ViewModelProviders.of(this).get(UserViewModel.class);
Caused by: java.lang.RuntimeException: Cannot create an instance of class UserViewModel Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor
在使用 ViewModelProviders
初始化 ViewModel
的子 class 时,默认情况下它希望您的 UserModel
class 具有零参数构造函数。
在您的情况下,您的构造函数具有参数 MutableLiveData<User> user
.
解决此问题的一种方法是为您的 UserModel
.
否则,如果您想为您的 ViewModel class 使用非零参数构造函数,您可能必须创建自定义 ViewModelFactory
class 来初始化您的 ViewModel 实例,它实现了 ViewModelProvider.Factory
接口。
我还没有尝试过,但是这里有一个 link 到一个优秀的 Google 示例:github.com/googlesamples/android-architecture-components。 具体来说,查看此 class GithubViewModelFactory.java for Java code and this class GithubViewModelFactory.kt 以获取相应的 Kotlin 代码。
ViewModelFactory
这将为我们提供来自 ViewModelModule
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels;
@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels) {
this.viewModels = viewModels;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
Provider<ViewModel> viewModelProvider = viewModels.get(modelClass);
if (viewModelProvider == null) {
throw new IllegalArgumentException("model class " + modelClass + " not found");
}
return (T) viewModelProvider.get();
}
}
ViewModelModule
负责将整个 ViewModel 类 绑定到 Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);
//You are able to declare ViewModelProvider.Factory dependency in another module. For example in ApplicationModule.
@Binds
@IntoMap
@ViewModelKey(UserViewModel.class)
abstract ViewModel userViewModel(UserViewModel userViewModel);
//Others ViewModels
}
ViewModelKey
是在地图中用作键的注释,看起来像
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
Class<? extends ViewModel> value();
}
现在您可以创建 ViewModel 并满足图中所有必要的依赖关系
public class UserViewModel extends ViewModel {
private UserFacade userFacade;
@Inject
public UserViewModel(UserFacade userFacade) { // UserFacade should be defined in one of dagger modules
this.userFacade = userFacade;
}
}
实例化 ViewModel
public class MainActivity extends AppCompatActivity {
@Inject
ViewModelFactory viewModelFactory;
UserViewModel userViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getAppComponent().inject(this);
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);
}
}
并且不要伪造将 ViewModelModule
添加到 modules
列表中
@Singleton
@Component(modules = {ApplicationModule.class, ViewModelModule.class})
public interface ApplicationComponent {
//
}
如果构造函数中有参数,则:
DAGGER 2 public @inject 依赖的构造函数
@Inject
public UserViewModel(UserFacade userFacade)
{
this.userFacade = userFacade;
}
否则dagger 2会给你报错"can not instantiate viewmodel object"
问题可以通过从 AndroidViewModel
扩展 UserModel
来解决,后者是应用程序上下文感知 ViewModel 并且需要 Application
仅参数构造函数。 (documentation)
Ex-(在科特林中)
class MyVm(application: Application) : AndroidViewModel(application)
这适用于版本 2.0.0-alpha1
。
我编写了一个库,它应该可以更直接、更清晰地实现这一点,不需要多重绑定或工厂样板,同时还可以在运行时进一步参数化 ViewModel
:
https://github.com/radutopor/ViewModelFactory
@ViewModelFactory
class UserViewModel(@Provided repository: Repository, userId: Int) : ViewModel() {
val greeting = MutableLiveData<String>()
init {
val user = repository.getUser(userId)
greeting.value = "Hello, $user.name"
}
}
在视图中:
class UserActivity : AppCompatActivity() {
@Inject
lateinit var userViewModelFactory2: UserViewModelFactory2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
appComponent.inject(this)
val userId = intent.getIntExtra("USER_ID", -1)
val viewModel = ViewModelProviders.of(this, userViewModelFactory2.create(userId))
.get(UserViewModel::class.java)
viewModel.greeting.observe(this, Observer { greetingText ->
greetingTextView.text = greetingText
})
}
}
2020 年初,Google 在 androidx 生命周期库的 2.2.0 版中弃用了 ViewModelProviders class。
不再需要使用 ViewModelProviders 来创建 ViewModel 的实例,您可以将 Fragment 或 Activity 实例传递给 ViewModelProvider 构造函数。
如果您使用如下代码:
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
您会收到一条警告,指出 ViewModelProviders 已被弃用。
您可以改为:
val viewModel = ViewModelProvider(this).get(CalculatorViewModel::class.java)
或者,要使用委托,请进行以下更改。
在build.gradle(Module:app)文件中,使用2.2.0版本的lifecycle 组件:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
另加
implementation "androidx.activity:activity-ktx:1.1.0"
如果您想使用 Fragment 中的 ViewModel,请使用
implementation "androidx.fragment:fragment-ktx:1.2.2"
fragment-ktx 自动包含 activity-ktx,所以你不需要 在依赖项中指定两者。
您需要在 android 部分指定 Java 8 :
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.kgandroid.calculator"
minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
kotlinOptions {
jvmTarget = "1.8"
}
}
在您的 Fragment 或 Activity 中,将导入更改为:
导入androidx.activity.viewModels
创建 ViewModel 的代码变为:
val viewModel: CalculatorViewModel by viewModels()
而不是
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
使用 viewModel 对象作为 :
val viewModel:viewModels() 的 CalculatorViewModel
viewModel.newNumber.observe(this, Observer { stringResult -> newNumber.setText(stringResult) })
其中 newNumer 是一个 LiveData 对象
In a Fragment that you want to share the Activity's ViewModel, you'd use
`val viewModel: CalculatorViewModel by activityViewModels()`
**That's the equivalent of passing the Activity instance in the (deprecated)
ViewModelProviders.of() function.**
创建一个不带任何参数的构造函数,即
Default/ No-arg constructor
在视图模型中 class .
在我的例子中,我忘记生成这个构造函数并在我学习时浪费了 30 分钟 - 之后它对我有用。
遇到这个问题的各位,我是这样遇到的:
1- 在您的 ViewModel 中,不要 创建构造函数,只需创建一个接受上下文和其他参数的函数
public class UserModel extends ViewModel {
private Context context;
private ..........;
public void init(Context context, ......) {
this.context = context;
this..... = ....;
}
// Your stuff
}
2- 在你的 activity:
UserViewModel viewModel = ViewModelProviders.of(this).get(UserViewModel.class);
viewModel.init(this, .....);
// You can use viewModel as you want
3- 在你的片段中
UserViewModel viewModel = ViewModelProviders.of(getActivity()).get(UserViewModel.class);
viewModel.init(getContext(), .....);
// You can use viewModel as you want
您可以通过视图模型工厂在视图模型中传递数据。您也可以查看this example以供参考。
class UserViewModelFactory(private val context: Context) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return UserViewModel(context) as T
}
}
class UserViewModel(private val context: Context) : ViewModel() {
private var listData = MutableLiveData<ArrayList<User>>()
init{
val userRepository : UserRepository by lazy {
UserRepository
}
if(context.isInternetAvailable()) {
listData = userRepository.getMutableLiveData(context)
}
}
fun getData() : MutableLiveData<ArrayList<User>>{
return listData
}
}
您可以在 activity 中调用视图模型,如下所示。
val userViewModel = ViewModelProviders.of(this,UserViewModelFactory(this)).get(UserViewModel::class.java)
我有同样的问题,通过将导航 ui 库添加到我的项目来修复它:
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
在我使用 HILT 的情况下,它在具有 ViewModel 的片段上方缺少一个注释:@AndroidEntryPoint
@AndroidEntryPoint
class BestFragment : Fragment() {
....
当然在您的 ViewModel class 您还需要使用 Annotate HILT 需要什么:@ViewModelInject
class BestFragmentViewModel @ViewModelInject constructor(var userManager: UserManager) : ViewModel() {
....
}
2020-07-29 10:13:25
对于 lifecycle_version = '2.2.0'
ViewProviders.of API 已弃用。这是我的情况 :
class MainActivityViewModel(application: Application) : AndroidViewModel(application) {
private var repository: UserRepository
val allUsers: LiveData<List<User>>
......
error:
val userViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
success:
val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application)
userViewModel = ViewModelProvider(this,factory).get(MainActivityViewModel::class.java)
通过 application
api ViewModelProvider.AndroidViewModelFactory.getInstance
关于
重建前不存在下面的类:
我有同样的错误。我正在使用 Hilt,在我的例子中,它缺少第二个 hilt 编译器依赖项
现在我有两个:
kapt com.google.dagger:hilt-android-compiler:#version
和
kapt androidx.hilt:hilt-compiler:#version
在我的应用级别 build.gradle 文件中,它有效。
com.google.dagger:hilt-android-compiler 在您使用 Hilt Android Gradle 插件时需要(参见 docs) 和 androidx.hilt:hilt-compiler:#version 当您想要集成 Hilt 和 Jetpack 时显然需要它,例如注入 Android Jetpack ViewModel(参见 docs)
如果您使用 hilt,您可能会忘记使用 @AndroidEntryPoint[ 注释您的 activity 或片段=10=]
我在使用 @ViewModelInject
时遇到了一些问题,因为它已被 HILT 弃用。
要解决此问题,请更改此代码:
class MainViewModel @ViewModelInject constructor(
val mainRepository: MainRepository
): ViewModel()
与:
@HiltViewModel
class MainViewModel @Inject constructor(
val mainRepository: MainRepository
): ViewModel()
当然,请记住在您的片段或 activity 上方添加 @AndroidEntryPoint
注释(无论您在哪里实例化 ViewModel
),如下所示:
@AndroidEntryPoint
class UsageFragment : Fragment(R.layout.fragment_usage) {
.
.
.
}
终极提示:
您可以立即查看 HILT 是否正常工作 查看 ViewModel
左侧是否有图标。
这里不行:
这里 它确实有效:
如果您在更新代码后没有看到它们,请单击 Build -> Rebuild Project
对于 Koin:
我遇到了这个问题,原来我只是从 AndroidX 导入了 viewModels() 而不是从 Koin
导入了 viewModel()此失败的最常见原因是 Fragment/Activity 开头缺少 @AndroidEntryPoint,如下所示:
@AndroidEntryPoint
class MyFragment : Fragment {
val viewModel by viewModels<MyViewModel>()
}
同样,您的 ViewModel 应由 HiltViewModel 注释,如下所示:
@HiltViewModel
class MyViewModel@Inject constructor(
private val var1: Type1
) : ViewModel()
如果您使用导航组合并在 NavHost 块内调用您的屏幕,则刀柄无法注入视图模型。为此,您可以使用这种方式;
NavHost(navHostController, startDestination = "HomeScreen") {
composable("HomeScreen") {
HomeScreen(homeScreenViewModel = hiltViewModel())
}
}
不要忘记为 hiltViewModel()
添加此依赖项 -> implementation("androidx.hilt:hilt-navigation-compose:1.0.0-alpha02")
如果您使用的是匕首柄和 2.31 或更高版本,则不要在视图模型中使用“ViewModelInject”class。 Dagger 正在提供使用 viewmodel 的新方法,因此请按照以下说明进行操作。
1:在 class 之上添加 @HiltViewModel 2: 使用 Inject intead of ViewModelInject
@HiltViewModel
class AuthViewModel @Inject constructor(
private val authRepository: AuthRepository,
...
) : ViewModel()
{...}
对于刀柄:
为主要活动和片段简单添加 @AndroidEntryPoint
,为视图模型添加 @HiltViewModel
之后的示例:
@HiltViewModel
class SplashViewModel @Inject constructor(
@AndroidEntryPoint
class SplashFragment : Fragment() {
private lateinit var b: SplashFragmentBinding
private val vm: SplashViewModel by viewModels()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding