使用Dagger2将适配器类注入Fragment

问题描述 投票:0回答:1

我已经按照Android架构蓝图Dagger2进行依赖注入:URL

现在我想将Adapter注入我的Fragment类:

@ActivityScoped
class MainFragment @Inject
constructor(): DaggerFragment(), ArtistClickCallback {

    @Inject lateinit var adapter : ArtistAdapter 
}

主要模块类:

@Module
abstract class MainModule {
    @FragmentScoped
    @ContributesAndroidInjector(modules = [MainFragmentModule::class])
    internal abstract fun mainFragment(): MainFragment

    @Binds
    internal abstract fun bindArtistClickCallback(mainFragment: MainFragment) : ArtistClickCallback
}

MainFragmentModule:

@Module
class MainFragmentModule {

    @Provides
    fun provideArtistAdapter() = ArtistAdapter()
}

这是我的适配器类:

 class ArtistAdapter @Inject constructor(
  private val artistClickCallback : ArtistClickCallback
) : PagedListAdapter<LastFmArtist, RecyclerView.ViewHolder>(POST_COMPARATOR)

当我构建项目时,我得到以下Kotlin编译器错误:

error: [Dagger/DependencyCycle] Found a dependency cycle:
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.sample.android.lastfm.LastFmApp> {
                ^
      com.sample.android.lastfm.ui.main.MainFragment is injected at


com.sample.android.lastfm.ui.main.MainModule.bindArtistClickCallback$app_debug(mainFragment)
  com.sample.android.lastfm.ArtistClickCallback is injected at
      com.sample.android.lastfm.ui.main.ArtistAdapter.artistClickCallback
  com.sample.android.lastfm.ui.main.ArtistAdapter is injected at
      com.sample.android.lastfm.ui.main.MainFragment.adapter
  com.sample.android.lastfm.ui.main.MainFragment is injected at
      com.sample.android.lastfm.ui.main.MainActivity.mainFragment
  com.sample.android.lastfm.ui.main.MainActivity is injected at
      dagger.android.AndroidInjector.inject(T) [com.sample.android.lastfm.di.AppComponent → com.sample.android.lastfm.di.ActivityBindingModule_MainActivity$app_debug.MainActivitySubcomponent]

你能建议我怎么解决这个问题吗?

代码可以在URL找到

android dagger-2
1个回答
0
投票

你的片段可能不应该有@ActivityScoped作为范围。进一步不要使用构造函数注入片段(或任何其他框架类型)!在某些情况下,Android框架会创建这些对象,您最终会在类中使用错误的引用。通过其构建器将片段添加到相应的组件。

您还使用了提供注释的方法以及构造函数注入(@Inject constructor())。选一个。既然你也在ArtistAdapter中使用场注入,你会遇到的下一个“错误”就是null callback because you don't inject the adapter。你只需创建对象。 通常应该优先考虑构造函数注入,这也将注入字段。完全删除以下内容,在construcor上保留注释:

@Provides
fun provideArtistAdapter() = ArtistAdapter()

继续前进,你的错误起源于MainActivitySubcomponent(最后一行),似乎是因为你的MainFragment被绑定为ArtistClickCallback,但需要一个需要ArtistAdapterArtistClickCallback ...因此你的依赖循环。

一旦你修复了上面提到的问题(在这种情况下就片段上的@Inject构造函数),这个问题应该自行解决,因为它来自MainFragment中由Dagger构建的MainActivitySubcomponent,这是错误的地方,因为你的片段应该有一个较低的范围比活动。

此外,您需要将绑定(@Binds fun bindArtistClickCallback)移动到MainFragmentModule中,因为在Activity组件中没有要绑定的片段(当前添加绑定的位置)

解决所有这些问题后,您将片段绑定到正确的FragmentSubcomponent,然后将其绑定为Callback,然后您可以使用它创建适配器,它应该可以工作。

我建议您对Dagger有更全面的了解,并确保了解指出的所有问题/修复。


这应该是它的样子

@FragmentScoped
class MainFragment(): DaggerFragment(), ArtistClickCallback {

  @Inject lateinit var adapter : ArtistAdapter 
}

@Module
abstract class MainModule {
  @FragmentScoped
  @ContributesAndroidInjector(modules = [MainFragmentModule::class])
  internal abstract fun mainFragment(): MainFragment
}

@Module
class MainFragmentModule {

  @Binds
  internal abstract fun bindArtistClickCallback(mainFragment: MainFragment) : ArtistClickCallback
}

class ArtistAdapter @Inject constructor(
  private val artistClickCallback : ArtistClickCallback
) : PagedListAdapter<LastFmArtist, RecyclerView.ViewHolder>(POST_COMPARATOR)
© www.soinside.com 2019 - 2024. All rights reserved.