I receive following error message from dagger at compile time. It finds a dependency cycle
in dagger :
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]
Here is my 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
}
}
Here is 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
}
}
Here is ActivityBindingModule :
@Module
abstract class ActivityBindingModule {
@ContributesAndroidInjector(
modules = [MainModule::class,
DetailModule::class]
)
internal abstract fun mainActivity(): MainActivity
}
And this is my DetailViewModel Factory :
/**
* 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")
}
}
I have injected factory at my 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)
}
}
I change my providePost
method by passing MainActivity as parameter instead of DetailFragment, and problem resolved :
@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
}