如何将viewModel注入到fragment - dagger 2



嗨,我使用dagger2的依赖注入,当我试图注入MainActivityViewModel在我的片段我得到错误lateinit property viewModelx has not been initialized

这些是相关的依赖文件和Fragment

RetroModule

@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

@Singleton
@Component(modules = [RetroModule::class])
interface RetroComponent {
fun inject(mainActivityViewModel: MainActivityViewModel)
}

片段

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 {}
}
}
错误更新

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

@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

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

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

@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
abstract fun provideMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel

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

@FragmentScope
@ContributesAndroidInjector
abstract fun provideCreditScoreFragment(): CreditScoreFragment

并且在你的片段中,当你声明视图模型时,有必要初始化它,例如使用延迟初始化,如你所愿:

private val viewModel: MainActivityViewModel by lazy {
ViewModelProvider(this, yourViewModelFactory).get(MainActivityViewModel::class.java)
}

最后你可以在片段中注入你的视图模型工厂(记住要在模块中声明工厂)

我想你错过了一些东西。在onAttach或onCreate中添加AndroidSupportInjection.inject(this),这将有助于dagger注入。

最新更新