【问题标题】:Hilt Inject into ViewModel without constructor params没有构造函数参数的 Hilt Inject 到 ViewModel
【发布时间】:2020-07-19 12:40:33
【问题描述】:

使用新的依赖注入库Hilt,如何在没有构造函数参数和ViewModelFactory的情况下将一些类注入ViewModel? 有可能吗?

Fragment 一样,我们仅使用@AndroidEntryPoint@Inject

【问题讨论】:

    标签: android dagger-hilt


    【解决方案1】:

    如何在没有构造函数参数和 ViewModelFactory 的情况下将一些类注入 ViewModel?有可能吗?

    Hilt 支持通过 @HiltViewModel(以前的 @ViewModelInject)注解对 ViewModel 进行构造函数注入。

    这允许任何 @AndroidEntryPoint-annotated 类将其 defaultViewModelProviderFactory 重新定义为 HiltViewModelFactory,从而允许创建 @HiltViewModel-annotated ViewModels 通过 Dagger/Hilt 正确实例化。

    新的 HILT 版本

    @HiltViewModel
    class RegistrationViewModel @Inject constructor(
        private val someDependency: SomeDependency,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {
        ...
    }
    

    旧 HILT 版本

    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
    

    【讨论】:

    • viewModels&lt;&gt;()是什么,无法导入
    • import androidx.fragment.app.viewModels in implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
    • androidx.fragment:fragment-ktx:1.2.5
    • 我认为问题在于如何将对象注入 ViewModel 而不是如何将 ViewModel 注入其他 android 组件。当我尝试在 ViewModel 上使用 @AndroidEntryPoint 时,它给了我一个错误提示,就像只支持 Android 组件一样。
    • @Dhunju_likes_to_Learn 因为它不是android入口点,它是一个视图模型,所以应该使用@HiltViewModel。虽然我看到我的答案已经过时,但我应该更新它。
    【解决方案2】:

    是的,可以在没有构造函数参数的情况下将依赖项注入ViewModel 类。首先我们需要创建一个带有@EntryPoint注解的新接口来访问它。

    入口点是一个接口,每个接口都有一个访问器方法 我们想要的绑定类型(包括它的限定符)。还有,界面 必须用 @InstallIn 注释以指定要在其中的组件 安装入口点。

    最佳做法是在使用它的类中添加新的入口点接口。

    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

    请注意,该接口使用@EntryPoint 进行注释,并且它是 安装在ApplicationComponent 因为我们想要依赖 来自 Application 容器的实例。

    @Module
    @InstallIn(ApplicationComponent.class)
    public class DatabaseModule {
    
        @Provides
        public static MyDao provideMyDao(MyDatabase db) {
            return db.MyDao();
        }
    
    }
    

    虽然上面的代码已经过测试并且可以正常工作,但是android官方不推荐将依赖注入到ViewModel中;除非我们知道自己在做什么,否则最好的方法是通过构造函数注入将依赖项注入ViewModel

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      相关资源
      最近更新 更多