Hilt Inject into ViewModel without constructor params

醉酒当歌 提交于 2021-02-08 05:59:13

问题


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 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();
    }

}

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!