Hilt 在没有构造函数参数的情况下注入 ViewModel
Hilt Inject into ViewModel without constructor params
使用新的依赖注入库 Hilt
,如何在没有构造函数参数和 ViewModelFactory
的情况下将一些 类 注入到 ViewModel
中?
可能吗?
和Fragment
一样,我们只使用@AndroidEntryPoint
和@Inject
。
how to inject some classes into ViewModel without constructor params and ViewModelFactory? Is it possible?
Hilt 支持通过 @HiltViewModel
(以前的 @ViewModelInject
)注解注入 ViewModel 的构造函数。
这允许任何 @AndroidEntryPoint
-注释的 class 将它们的 defaultViewModelProviderFactory
重新定义为 HiltViewModelFactory
,这允许创建 @HiltViewModel
-注释的ViewModels 通过 Dagger/Hilt.
正确实例化
新刀柄版本:
@HiltViewModel
class RegistrationViewModel @Inject constructor(
private val someDependency: SomeDependency,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
旧版刀柄:
class RegistrationViewModel @ViewModelInject constructor(
private val someDependency: SomeDependency,
@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
然后
@AndroidEntryPoint
class ProfileFragment: Fragment(R.layout.profile_fragment) {
private val viewModel by viewModels<RegistrationViewModel>() // <-- uses defaultViewModelProviderFactory
是的,可以在没有构造函数参数的情况下将依赖项注入 ViewModel
class。首先我们需要创建一个用@EntryPoint
注释的新接口来访问它。
An entry point is an interface with an accessor method for each
binding type we want (including its qualifier). Also, the interface
must be annotated with @InstallIn
to specify the component in which to
install the entry point.
最佳做法是在使用它的 class 中添加新的入口点接口。
public class HomeViewModel extends ViewModel {
LiveData<List<MyEntity>> myListLiveData;
@ViewModelInject
public HomeViewModel(@ApplicationContext Context context) {
myListLiveData = getMyDao(context).getAllPosts();
}
public LiveData<List<MyEntity>> getAllEntities() {
return myListLiveData;
}
@InstallIn(ApplicationComponent.class)
@EntryPoint
interface MyDaoEntryPoint {
MyDao myDao();
}
private MyDao getMyDao(Context appConext) {
MyDaoEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(
appConext,
MyDaoEntryPoint.class
);
return hiltEntryPoint.myDao();
}
}
在上面的代码中,我们创建了一个名为 getMyDao
的方法,并使用 EntryPointAccessors
从应用程序容器中检索 MyDao
。
Notice that the interface is annotated with the @EntryPoint
and it's
installed in the ApplicationComponent
since we want the dependency
from an instance of the Application container.
@Module
@InstallIn(ApplicationComponent.class)
public class DatabaseModule {
@Provides
public static MyDao provideMyDao(MyDatabase db) {
return db.MyDao();
}
}
虽然上面的代码已经过测试并且可以正常工作,但是 android 官方不推荐将依赖项注入 ViewModel 的方法;除非我们知道我们在做什么,否则最好的方法是通过构造函数注入将依赖注入 ViewModel
。
使用新的依赖注入库 Hilt
,如何在没有构造函数参数和 ViewModelFactory
的情况下将一些 类 注入到 ViewModel
中?
可能吗?
和Fragment
一样,我们只使用@AndroidEntryPoint
和@Inject
。
how to inject some classes into ViewModel without constructor params and ViewModelFactory? Is it possible?
Hilt 支持通过 @HiltViewModel
(以前的 @ViewModelInject
)注解注入 ViewModel 的构造函数。
这允许任何 @AndroidEntryPoint
-注释的 class 将它们的 defaultViewModelProviderFactory
重新定义为 HiltViewModelFactory
,这允许创建 @HiltViewModel
-注释的ViewModels 通过 Dagger/Hilt.
新刀柄版本:
@HiltViewModel
class RegistrationViewModel @Inject constructor(
private val someDependency: SomeDependency,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
旧版刀柄:
class RegistrationViewModel @ViewModelInject constructor(
private val someDependency: SomeDependency,
@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
然后
@AndroidEntryPoint
class ProfileFragment: Fragment(R.layout.profile_fragment) {
private val viewModel by viewModels<RegistrationViewModel>() // <-- uses defaultViewModelProviderFactory
是的,可以在没有构造函数参数的情况下将依赖项注入 ViewModel
class。首先我们需要创建一个用@EntryPoint
注释的新接口来访问它。
An entry point is an interface with an accessor method for each binding type we want (including its qualifier). Also, the interface must be annotated with
@InstallIn
to specify the component in which to install the entry point.
最佳做法是在使用它的 class 中添加新的入口点接口。
public class HomeViewModel extends ViewModel {
LiveData<List<MyEntity>> myListLiveData;
@ViewModelInject
public HomeViewModel(@ApplicationContext Context context) {
myListLiveData = getMyDao(context).getAllPosts();
}
public LiveData<List<MyEntity>> getAllEntities() {
return myListLiveData;
}
@InstallIn(ApplicationComponent.class)
@EntryPoint
interface MyDaoEntryPoint {
MyDao myDao();
}
private MyDao getMyDao(Context appConext) {
MyDaoEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(
appConext,
MyDaoEntryPoint.class
);
return hiltEntryPoint.myDao();
}
}
在上面的代码中,我们创建了一个名为 getMyDao
的方法,并使用 EntryPointAccessors
从应用程序容器中检索 MyDao
。
Notice that the interface is annotated with the
@EntryPoint
and it's installed in theApplicationComponent
since we want the dependency from an instance of the Application container.
@Module
@InstallIn(ApplicationComponent.class)
public class DatabaseModule {
@Provides
public static MyDao provideMyDao(MyDatabase db) {
return db.MyDao();
}
}
虽然上面的代码已经过测试并且可以正常工作,但是 android 官方不推荐将依赖项注入 ViewModel 的方法;除非我们知道我们在做什么,否则最好的方法是通过构造函数注入将依赖注入 ViewModel
。