首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将viewModel注入fragment - dagger 2

如何将viewModel注入fragment - dagger 2
EN

Stack Overflow用户
提问于 2021-08-20 19:39:00
回答 1查看 800关注 0票数 0

您好,我正在使用dagger 2进行依赖项注入,当我尝试在片段中注入MainActivityViewModel时,我得到了错误lateinit property viewModelx has not been initialized

这些是相关的依赖文件和片段

RetroModule

代码语言:javascript
运行
复制
@Module
class RetroModule {

    @Singleton
    @Provides
    fun getRetrofitInstance(): Retrofit {
        return Retrofit.Builder()
            .baseUrl(baseURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    @Singleton
    @Provides
    fun getApiService(): ApiServiceInterface =
        getRetrofitInstance().create(ApiServiceInterface::class.java)

    companion object {
        private val baseURL = "https://android-interview.s3.eu-west-2.amazonaws.com/"
    }
}

RetroComponent

代码语言:javascript
运行
复制
@Singleton
@Component(modules = [RetroModule::class])
interface RetroComponent {

    fun inject(mainActivityViewModel: MainActivityViewModel)
}

片段

代码语言:javascript
运行
复制
class CreditScoreFragment : Fragment() {

    @Inject lateinit var viewModelx: MainActivityViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentCreditScoreBinding.inflate(inflater, container, false)
        val view = binding.root
        initViewModel()
        initView()
        return view
    }

    private fun initViewModel() {
        viewModelx.getCreditReportObserver().observe(viewLifecycleOwner, Observer<CreditReport> {
            showScoreUI(true)
            binding.score.text = it.creditReportInfo.score.toString()
            binding.maxScoreValue.text = "out of ${it.creditReportInfo.maxScoreValue}"
            initDonutView(
                it.creditReportInfo.score.toFloat(),
                it.creditReportInfo.maxScoreValue.toFloat()
            )
        })
        viewModelx.getServerErrorLiveDataObserver().observe(viewLifecycleOwner, Observer<Boolean> {
            if(it) {
                showScoreUI(false)
                showToastMessage()
            }
        })
        viewModelx.getCreditReport()
    }

 companion object {
        @JvmStatic
        fun newInstance() =
            CreditScoreFragment().apply {}
    }

}

错误更新

代码语言:javascript
运行
复制
xxx/app/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/ViewModelModule.java:18: error: @Binds methods' parameter type must be assignable to the return type
    public abstract androidx.lifecycle.ViewModelProvider.Factory bindMainActivityViewModel_Factory(@org.jetbrains.annotations.NotNull()
                                                                 ^xxx/app/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/RetroComponent.java:18: error: @Component.Factory abstract methods must return the @Component type or a supertype of the @Component. Inherited method: create(T)
    public static abstract class Factory implements dagger.android.AndroidInjector.Factory<com.example.clearscore.MyApplication> {
                           ^xxxapp/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/RetroComponent.java:6: error: com.example.clearscore.di.ViewModelModule has errors
@dagger.Component(modules = {com.example.clearscore.di.RetroModule.class, com.example.clearscore.di.ViewModelModule.class})

ViewModelModule

代码语言:javascript
运行
复制
@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(MainActivityViewModel::class )
    // Bind your View Model here
    abstract fun bindMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel

    @Binds
    // Bind viewModelFactory if you have custom ViewModelFactory
    abstract fun bindMainActivityViewModel_Factory(factory: MainActivityViewModel_Factory): ViewModelProvider.Factory
}

MainActivityViewModel_Factory

代码语言:javascript
运行
复制
@DaggerGenerated
@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class MainActivityViewModel_Factory implements Factory<MainActivityViewModel> {
  private final Provider<DataRepository> dataRepositoryProvider;

  public MainActivityViewModel_Factory(Provider<DataRepository> dataRepositoryProvider) {
    this.dataRepositoryProvider = dataRepositoryProvider;
  }

  @Override
  public MainActivityViewModel get() {
    return newInstance(dataRepositoryProvider.get());
  }

  public static MainActivityViewModel_Factory create(
      Provider<DataRepository> dataRepositoryProvider) {
    return new MainActivityViewModel_Factory(dataRepositoryProvider);
  }

  public static MainActivityViewModel newInstance(DataRepository dataRepository) {
    return new MainActivityViewModel(dataRepository);
  }
}
EN

回答 1

Stack Overflow用户

发布于 2021-08-20 20:05:43

您需要在视图模型模块中声明提供程序:

代码语言:javascript
运行
复制
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
abstract fun provideMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel

你的片段也必须在你的模块中声明:

代码语言:javascript
运行
复制
@FragmentScope
@ContributesAndroidInjector
abstract fun provideCreditScoreFragment(): CreditScoreFragment

在您的代码片段中,当您声明viewmodel时,需要初始化它,例如使用延迟初始化,正如您所希望的那样:

代码语言:javascript
运行
复制
 private val viewModel: MainActivityViewModel by lazy {
        ViewModelProvider(this, yourViewModelFactory).get(MainActivityViewModel::class.java)
 }

最后,您可以在片段中注入视图模型工厂(请记住在模块中声明工厂)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68867346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档