简体   繁体   中英

how to inject viewModel into a fragment - dagger 2

Hi I am using dagger 2 for dependency injection and when I try to inject MainActivityViewModel in my fragment I get the error lateinit property viewModelx has not been initialized

these are the related dependency files and 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)
}

Fragment

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 {}
    }

}

Error update

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

You need to declare the provider in your viewmodel module:

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

I think you are missing onething. Add AndroidSupportInjection.inject(this) in onAttach or onCreate based on when u start using your dependency this will help dagger to inject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM