Dagger 2 - IncompatiblyScopedBindings

Dagger 2 - IncompatiblyScopedBindings

我正在尝试使用 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")
    }
}

您将不得不 annotate FeedMeApplicationComponent@Singleton。因为 NetworkModuleNutritionModule 都定义了 @Provides 作用域为 @Singleton 的函数,任何使用这些模块的组件也必须将其自己的作用域指定为 @Singleton.

来自 Dagger docs:-

Since Dagger 2 associates scoped instances in the graph with instances of component implementations, the components themselves need to declare which scope they intend to represent. For example, it wouldn’t make any sense to have a @Singleton binding and a @RequestScoped binding in the same component because those scopes have different lifecycles and thus must live in components with different lifecycles. To declare that a component is associated with a given scope, simply apply the scope annotation to the component interface.