Кинжал 2 - Несовместимо ScopedBindings - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь создать базовую c архитектуру с Dagger 2 для моего учебного проекта, но я столкнулся с несколькими проблемами с ним…

Текущие ошибки кинжалы говорят мне

FeedMeApplicationComponent.java:7: error: [Dagger/IncompatiblyScopedBindings] .FeedMeApplicationComponent (unscoped) may not reference scoped bindings:

Эта проблема возникает только при добавлении ActivityMainModule в качестве модуля приложения

, а ActivityMainModule содержит подкомпонент, относящийся только к MainActivity.

Я не понимаю, почему я не могу добавить этот модуль подкомпонента в граф приложений: сбивающий с толку

Это мои классы Кинжала…

class FeedMeApplication : DaggerApplication() {

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerFeedMeApplicationComponent.factory().create(this)
    }
}
@Component(modules = [AndroidInjectionModule::class, NetworkModule::class, NutritionModule::class, ActivityMainModule::class])
interface FeedMeApplicationComponent : AndroidInjector<FeedMeApplication> {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): FeedMeApplicationComponent
    }

    override fun inject(instance: FeedMeApplication?)
}
@Module
object NetworkModule {

    @Singleton
    @Provides
    @JvmStatic
    fun provideNutritionService(retrofit: Retrofit): NutritionService {
        return retrofit.create(NutritionService::class.java)
    }

    @Singleton
    @Provides
    @JvmStatic
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .addConverterFactory(MoshiConverterFactory.create())
            .baseUrl("https://api.edamam.com/api")
            .client(okHttpClient)
            .build()
    }

    @Singleton
    @Provides
    @JvmStatic
    fun provideOkHttp(): OkHttpClient {
        return OkHttpClient()
            .newBuilder()
            .addInterceptor(ApiInterceptor())
            .build()
    }

    private class ApiInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request().newBuilder()
            request
                .addHeader("api_id", “abc")
                .addHeader("app_key", “123")
            return chain.proceed(request.build())
        }
    }
}
@Module
object NutritionModule {

    @Singleton
    @Provides
    @JvmStatic
    fun provideNutritionRepository(nutritionService: NutritionService): NutritionRepository {
        return NutritionRepository(nutritionService)
    }
}
@Module(subcomponents = [MainActivityComponent::class], includes = [MainModule::class])
abstract class ActivityMainModule {
    @Binds
    @IntoMap
    @ClassKey(MainActivity::class)
    abstract fun bindAndroidInjector(factory: MainActivityComponent.Factory): AndroidInjector.Factory<*>
}

@Module
object MainModule {

    @Singleton
    @Provides
    @JvmStatic
    fun provideMainViewModelFactory(nutritionRepository: NutritionRepository): MainViewModel.Factory {
        return MainViewModel.Factory(nutritionRepository)
    }

    @Provides
    @JvmStatic
    fun provideMainViewModel(
        viewModelFactory: MainViewModel.Factory,
        fragmentActivity: FragmentActivity
    ): MainViewModel {
        return ViewModelProviders.of(fragmentActivity, viewModelFactory)
            .get(MainViewModel::class.java)
    }
}
@ActivityScope
@Subcomponent
interface MainActivityComponent : AndroidInjector<MainActivity> {

    @Subcomponent.Factory
    interface Factory : AndroidInjector.Factory<MainActivity> {}
}
class MainActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var mainViewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mainViewModel.liveDataFoodAnalysis.observe(this, Observer { food ->
            Log.d("Food answer", food.uri)
        })
        mainViewModel.getFoodAnalysisResponse("egg")
    }
}

1 Ответ

1 голос
/ 26 апреля 2020

Вам придется annotate FeedMeApplicationComponent с @Singleton. поскольку и NetworkModule, и NutritionModule определяют функции @Provides, ограниченные @Singleton, любой компонент, использующий эти модули, должен также указать свою собственную область видимости как @Singleton.

From Dagger docs : -

Поскольку Dagger 2 связывает экземпляры области в графе с экземплярами реализаций компонентов, самим компонентам необходимо объявить, какую область они намерены представлять. Например, не имеет смысла иметь привязку @Singleton и привязку @RequestScoped в одном и том же компоненте, поскольку эти области имеют разные жизненные циклы и, следовательно, должны жить в компонентах с разными жизненными циклами. Чтобы объявить, что компонент связан с заданной областью действия, просто примените аннотацию области действия к интерфейсу компонента.

...