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