问题
With the new dependency injection library Hilt
, how to inject some classes into ViewModel
without constructor params and ViewModelFactory
?
Is it possible?
Like in Fragment
, we use only @AndroidEntryPoint
and @Inject
.
回答1:
how to inject some classes into ViewModel without constructor params and ViewModelFactory? Is it possible?
Hilt supports constructor injection of ViewModel via the @ViewModelInject
annotation.
This allows for any @AndroidEntryPoint
-annotated class to redefine their defaultViewModelProviderFactory
to be the HiltViewModelFactory
, which allows the creation of @ViewModelInject
-annotated ViewModels correctly instantiated via Dagger/Hilt.
class RegistrationViewModel @ViewModelInject constructor(
private val someDependency: SomeDependency,
@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
And
@AndroidEntryPoint
class ProfileFragment: Fragment(R.layout.profile_fragment) {
private val viewModel by viewModels<RegistrationViewModel>() // <-- uses defaultViewModelProviderFactory
回答2:
Yes, it is possible to inject dependency into a ViewModel
class without constructor params. First we need to create a new interface annotated with @EntryPoint
to access it.
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.
The best practice is adding the new entry point interface inside the class that uses it.
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();
}
}
In the code above we created a method named getMyDao
and used EntryPointAccessors
to retrieve MyDao
from Application container.
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();
}
}
Though the code above has been tested and worked properly but it is not the recommended way to inject dependency into ViewModel by android officials; and unless we know what we're doing, the best way is to inject dependency into ViewModel
through constructor injection.
来源:https://stackoverflow.com/questions/62980426/hilt-inject-into-viewmodel-without-constructor-params