【问题标题】:How install view model in fragmentComponent with Hilt injection?如何使用 Hilt 注入在 fragmentComponent 中安装视图模型?
【发布时间】:2020-12-28 16:43:06
【问题描述】:

我想要范围 ViewModel,它是 Fragment 而不是活动的依赖项,

interface MarsRepository {
    suspend fun getProperties(): List<Mars>
}



@Module
@InstallIn(FragmentComponent::class)
class MarsRepositoryModule {
    
    @Provides
    fun bindRemoteMarsDataSource(): MarsRepository{
        return RemoteMarsStorageImp()
    }
}



class MarsViewModel @ViewModelInject constructor(private val repository: MarsRepository): ViewModel()



@AndroidEntryPoint
class MarsFragment: Fragment() {
    
    val viewModel by viewModels<MarsViewModel>()
}

但我得到了这个

/app/build/generated/source/kapt/debug/com/Sample/bestcase/DevByteApplication_HiltComponents.java:111: error: [Dagger/MissingBinding] com.Sample.domain.repository.MarsRepository cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements DevByteApplication_GeneratedInjector,
                         ^
      javax.inject.Provider<com.Sample.domain.repository.MarsRepository> is injected at
          com.Sample.bestcase.features.mars.MarsViewModel_AssistedFactory(repository)
      com.Sample.bestcase.features.mars.MarsViewModel_AssistedFactory is injected at
          com.Sample.bestcase.features.mars.MarsViewModel_HiltModule.bind(factory)
      java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
          androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(…, viewModelFactories)
      @dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is requested at
          dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getActivityViewModelFactory() [com.Sample.bestcase.DevByteApplication_HiltComponents.SingletonC → com.Sample.bestcase.DevByteApplication_HiltComponents.ActivityRetainedC → com.Sample.bestcase.DevByteApplication_HiltComponents.ActivityC]
  The following other entry points also depend on it:
      dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getFragmentViewModelFactory() [com.Sample.bestcase.DevByteApplication_HiltComponents.SingletonC → com.Sample.bestcase.DevByteApplication_HiltComponents.ActivityRetainedC → com.Sample.bestcase.DevByteApplication_HiltComponents.ActivityC → com.Sample.bestcase.DevByteApplication_HiltComponents.FragmentC]

只有通过 ActivityComponent 安装才能工作

@Module
@InstallIn(ActivityComponent::class)
class MarsRepositoryModule { 
    @Provides
    fun bindRemoteMarsDataSource(): MarsRepository{
        return RemoteMarsStorageImp()
    }
}

当我跟踪代码时,它使用 DefaultActivityViewModelFactory 而不是 DefaultFragmentViewModelFactory

 /**
     * Hilt Modules for providing the activity level ViewModelFactory
     */
    @Module
    @InstallIn(ActivityComponent.class)
    public abstract static class ActivityModule {

        @NonNull
        @Multibinds
        abstract Map<String, ViewModelAssistedFactory<? extends ViewModel>> viewModelFactoriesMap();

        @Provides
        @IntoSet
        @NonNull
        @DefaultActivityViewModelFactory
        static ViewModelProvider.Factory provideFactory(
                @NonNull Activity activity,
                @NonNull Application application,
                @NonNull Map<String, Provider<ViewModelAssistedFactory<? extends ViewModel>>>
                        viewModelFactories) {
            // Hilt guarantees concrete activity is a subclass of ComponentActivity.
            SavedStateRegistryOwner owner = (ComponentActivity) activity;
            Bundle defaultArgs = activity.getIntent() != null
                    ? activity.getIntent().getExtras() : null;
            SavedStateViewModelFactory delegate =
                    new SavedStateViewModelFactory(application, owner, defaultArgs);
            return new HiltViewModelFactory(owner, defaultArgs, delegate, viewModelFactories);
        }
    }

    /**
     * Hilt Modules for providing the fragment level ViewModelFactory
     */
    @Module
    @InstallIn(FragmentComponent.class)
    public static final class FragmentModule {

        @Provides
        @IntoSet
        @NonNull
        @DefaultFragmentViewModelFactory
        static ViewModelProvider.Factory provideFactory(
                @NonNull Fragment fragment,
                @NonNull Application application,
                @NonNull Map<String, Provider<ViewModelAssistedFactory<? extends ViewModel>>>
                        viewModelFactories) {
            Bundle defaultArgs = fragment.getArguments();
            SavedStateViewModelFactory delegate =
                    new SavedStateViewModelFactory(application, fragment, defaultArgs);
            return new HiltViewModelFactory(fragment, defaultArgs, delegate, viewModelFactories);
        }

        private FragmentModule() {
        }
    }

【问题讨论】:

    标签: android dagger dagger-hilt


    【解决方案1】:

    视图模型已被其片段限定。编译器试图告诉您的是,您正在尝试将 repository 注入到组件中,该组件的寿命比片段长。

    正如它在组件部分中所说的here

    每个组件负责注入不同类型的 Android 类。如下表所示:

    为了在视图模型中注入依赖项,它必须至少是ActivityRetainedScoped


    修复

    FragmentComponent::class 更改为ActivityRetainedComponent::classSingletonComponent::class

    @Module
    @InstallIn(SingletonComponent::class) // or at least ActivityRetainedComponent
    class MarsRepositoryModule { 
        @Provides
        fun bindRemoteMarsDataSource(): MarsRepository{
            return RemoteMarsStorageImp()
        }
    }
    

    【讨论】:

    • 它已经在使用 ActivityComponent,但我希望 scop ViewModel 分段而不是活动!!。每个片段都有自己的 ViewModel 实例,而不是共享实例。
    • 我不知道您所说的“我想将 ViewModel 限定为片段而不是活动”是什么意思。视图模型已经限定在片段范围内。当您编写by viewModels&lt;T&gt;() 时,您的视图模型的范围是相应的片段。这与您在视图模型中的存储库范围无关。如果你希望你的视图模型是活动范围的,那么你写by activityViewModel()
    • 我的意思是存储库的范围与 ViewModel 相同。如果它是按片段划分的,那么为什么它使用 DefaultActivityViewModelFactory 来提供视图模型?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    • 2021-01-19
    • 2011-10-23
    相关资源
    最近更新 更多