Внедрить адаптер во фрагмент с помощью Dagger2

Я следовал Android Architecture Blueprints Dagger2 для внедрения зависимостей: https://github.com/googlesamples/android-architecture/tree/todo-mvp-кинжал

Теперь я хочу внедрить адаптер в свой класс Fragment:

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

    @Inject lateinit var adapter : ArtistAdapter 
}

И у меня есть следующее в классе модуля:

@Module
abstract class MainModule {
    @FragmentScoped
    @ContributesAndroidInjector
    internal abstract fun mainFragment(): MainFragment

    @Module
    companion object {
        @Provides
        @ActivityScoped
        @JvmStatic internal fun provideArtistAdapter() = ArtistAdapter()
    }
}

Но по какой-то причине он не может отображать данные в RecyclerView. Когда я не использую инъекцию, а просто использую val adapter = ArtistAdapter(), это работает.

Чего мне не хватает в инъекциях с помощью Dagger2?

Дополнения:

mainFragment реализует обратный вызов как прослушиватель кликов:

interface ArtistClickCallback {
    fun onClick(artist: LastFmArtist, poster : ImageView)
}

И :

class MainFragment : DaggerFragment(), ArtistClickCallback

А вот модуль фрагмента:

@Module
class MainFragmentModule {

    @Provides
    fun provideArtistAdapter(mainFragment: MainFragment) = ArtistAdapter(mainFragment)

}

Но я получаю следующее исключение, когда удаляю @Inject из конструктора фрагментов:

error: [Dagger/MissingBinding] com.sample.android.lastfm.ui.main.MainFragment cannot be provided without an @Inject constructor or an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.sample.android.lastfm.LastFmApp> {
                ^
  A binding with matching key exists in component: com.sample.android.lastfm.ui.main.MainModule_MainFragment$app_debug.MainFragmentSubcomponent
      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]

1. Вы не должны использовать аннотацию @Inject в конструкторе Fragment. 2. Вы должны использовать ту же область видимости — FragmentScoped в MainFragment и сопутствующем объекте. 3. В onAttach или onCreate фрагмента вы должны вызвать DaggerFragmentComponent.inject(fragment).

jczerski 28.01.2019 14:22

Посмотрите на пример Google, где они использовали аннотацию @inject в конструкторе: github.com/googlesamples/android-architecture/blob/…

Ali 28.01.2019 14:30

Есть ли какая-то конкретная причина, по которой вы хотите ввести адаптер? Есть ли в этом практическая польза? Я видел это раньше, но я не уверен, что оно того стоит.

EpicPandaForce 28.01.2019 15:55

@EpicPandaForce Нет, особой причины нет. Я просто спросил с целью обучения.

Ali 28.01.2019 16:57
2
4
1 256
1

Ответы 1

Удалите конструктор @Inject from Fragment и предоставьте адаптер фрагменту или используйте конструктор ввода в своем адаптере.

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

} 

-

@Module
class MyAwesomeFragmentModule {

    @Provides
    fun provideArtistAdapter() = ArtistAdapter()

}

Спасибо @Исмаэль Ди Вита. Я получаю исключение, когда я строю. Пожалуйста, посмотрите раздел addenda в моем вопросе.

Ali 20.02.2019 12:52

Другие вопросы по теме