Инжекция кинжала ViewModel Factory ошибка времени компиляции (цикл зависимости в кинжале) - PullRequest
1 голос
/ 14 февраля 2020

Я получаю следующее сообщение об ошибке от кинжала во время компиляции. Он находит dependency cycle в кинжале:

public abstract interface AppComponent extends dagger.android.AndroidInjector<com.sample.android.storytel.StorytelApplication> {
            ^
  androidx.lifecycle.ViewModelProvider.Factory is injected at
      com.sample.android.storytel.ui.DetailFragment.factory
  com.sample.android.storytel.ui.DetailFragment is injected at
      com.sample.android.storytel.di.DetailModule.providePost$app_debug(fragment)
  com.sample.android.storytel.domain.Post is injected at
      com.sample.android.storytel.viewmodels.DetailViewModel.Factory(…, post)
  com.sample.android.storytel.viewmodels.DetailViewModel.Factory is injected at
      com.sample.android.storytel.di.DetailModule.bindViewModelFactory$app_debug(factory)
  androidx.lifecycle.ViewModelProvider.Factory is injected at
      com.sample.android.storytel.ui.DetailFragment.factory
  com.sample.android.storytel.ui.DetailFragment is injected at
      dagger.android.AndroidInjector.inject(T) [com.sample.android.storytel.di.AppComponent → com.sample.android.storytel.di.ActivityBindingModule_MainActivity$app_debug.MainActivitySubcomponent → com.sample.android.storytel.di.DetailModule_DetailFragment$app_debug.DetailFragmentSubcomponent]

Вот мой DetailModule:

@Module
abstract class DetailModule {

    @ContributesAndroidInjector
    internal abstract fun detailFragment(): DetailFragment

    @Binds
    internal abstract fun bindViewModelFactory(factory: DetailViewModel.Factory): ViewModelProvider.Factory

    @Module
    companion object {

        @Provides
        @JvmStatic
        internal fun providePost(fragment: DetailFragment): Post =
            DetailFragmentArgs.fromBundle(fragment.arguments!!).post
    }
}

Вот AppComponent:

@Singleton
@Component(
    modules = [ActivityBindingModule::class,
        AndroidSupportInjectionModule::class,
        Network::class,
        BaseModule::class]
)
interface AppComponent : AndroidInjector<StorytelApplication> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        fun build(): AppComponent
    }
}

Вот ActivityBindingModule:

@Module
abstract class ActivityBindingModule {

    @ContributesAndroidInjector(
        modules = [MainModule::class,
            DetailModule::class]
    )
    internal abstract fun mainActivity(): MainActivity
}

И это моя фабрика DetailViewModel:

/**
     * Factory for constructing DetailViewModel with parameter
     */
    class Factory @Inject constructor(
        private val useCase: DetailUseCase,
        val post: Post
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(DetailViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return DetailViewModel(useCase, post) as T
            }
            throw IllegalArgumentException("Unable to construct viewmodel")
        }
    }

Я вставил фабрику в мой DetailFragment:

class DetailFragment @Inject
constructor() // Required empty public constructor
    : DaggerFragment() {

    @Inject
    lateinit var factory: DetailViewModel.Factory

    private val viewModel: DetailViewModel by lazy {
        ViewModelProviders.of(this, factory)
            .get(DetailViewModel::class.java)
    }
}

Здесь вы можете найти исходный код: https://github.com/Ali-Rezaei/Colors

1 Ответ

0 голосов
/ 14 февраля 2020

Я изменяю свой метод providePost, передавая MainActivity в качестве параметра вместо DetailFragment, и проблема решается:

        @Provides
        @JvmStatic
        internal fun providePost(activity: MainActivity): Post {
            val navHostFragment = activity.supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment)
            val fragment = navHostFragment?.childFragmentManager?.fragments?.get(0);
            return DetailFragmentArgs.fromBundle(fragment?.arguments!!).post
        }
...