Dagger 2:@Component.Builder 缺少所需模块或组件的设置器:[appi.example.com.dagger.AppModule]`

Posted

技术标签:

【中文标题】Dagger 2:@Component.Builder 缺少所需模块或组件的设置器:[appi.example.com.dagger.AppModule]`【英文标题】:Dagger 2: @Component.Builder is missing setters for required modules or components: [appi.example.com.dagger.AppModule]` 【发布时间】:2017-10-20 08:42:27 【问题描述】:

我正在配置新的 Dagger android 模块,但出现此错误 这是我的组件:

@AppScope
@Component(modules = AppModule.class, NetModule.class)
public interface AppComponent 

  @Component.Builder
  interface Builder 
    @BindsInstance
    Builder application(ExampleApplication application);

    @BindsInstance
    Builder appModule(AppModule appModule);

    @BindsInstance
    Builder netModule(NetModule netModule);

    AppComponent build();
  

  void inject(ExampleApplication __); 
...

我在我的应用程序中这样构建

appComponent = DaggerAppComponent
      .builder()
      .application(this)
      .appModule(new AppModule(this))
      .netModule(new NetModule())
      .build()
      .inject(this);

但我仍然收到错误

错误:(20, 3) 错误:@Component.Builder 缺少所需模块或组件的设置器:[app.example.com.dagger.AppModule]

根据应该是正确的文档,我错过了什么?

例如,这可能是带有 Builder 的有效组件:

@Component(modules = BackendModule.class, FrontendModule.class)
interface MyComponent 
  MyWidget myWidget();

  @Component.Builder
  interface Builder 
    MyComponent build();
    Builder backendModule(BackendModule bm);
    Builder frontendModule(FrontendModule fm);
  

【问题讨论】:

您是否尝试过在您的模块方法中不使用@BindsInstance @DavidMedenjak 我正在关注这个tutorial 哪个模块应该有这个?应用模块? 如果你看看你上面提供的代码,一个是你自己的,另一个是匕首文档的一部分。明显的区别是,you 在您的 AppModuleNetModule 构建器方法上有一个 @BindsInstance 注释。 我也遇到了同样的问题 【参考方案1】:

Kotlin 答案

检查模块的构造函数。

如果你有构造函数和应用参数,删除它。

真实用法:

@Module
class MyModule  
   // This is example module for true usage.

••• 错误用法:

@Module
class MyModule constructor(application: Application)  
   // This is example module for wrong usage.

【讨论】:

【参考方案2】:

在我的例子中,我使用了一个对象模块,所以我不得不用 @JvmStatic 注释提供者方法

@Module
object GsonModule 

    @JvmStatic
    @Singleton
    @Provides
    fun provideGson() = Gson()


【讨论】:

代码 sn-p 将有助于更好地理解答案(并获得更多支持) @Module object MainActivityModule @JvmStatic @Provides @ActivityScope fun provideZzz(activity: MainActivity): Zzz return Zzz(activity) 【参考方案3】:

我认为这对@BindsInstance的使用和@Provides Application、Dagger 2 Component Builder的删除提供了一个更清晰的解释:

@BindsInstance什么?

这是定义:

标记组件构建器或子组件构建器上的方法 允许实例绑定到 零件。 —— 来源

什么?我也看不懂?

以下是何时使用它的简单提示:

@BindsInstance 方法应该优先于编写@Module 构造函数参数并立即提供这些值。 —— 来源

我来自 Spring Boot,而 Dagger 2 是 OMG 复杂得多。 :(

因此,根据我对 Dagger 2 极其有限的经验,发生这种情况是因为 *Module 的构造函数参数配置不正确。我仍然不知道如何使用构造函数参数正确配置模块,但我宁愿遵循 Dagger 2 文档给出的推荐方法,即删除构造函数参数并改用 @BindsInstance@Inject .

例如

@Module
class NetModule  // no constructor argument here!

    @Inject @Named("mqttServer") // replaced by @Inject
    internal lateinit var mqttServer: String


AppComponent

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, NetModule::class, ActivityBuilder::class])
interface AppComponent 

    @Component.Builder
    interface Builder 
        @BindsInstance
        fun application(application: Application): Builder

        @BindsInstance // you'll call this when setting up Dagger
        fun mqttServer(@Named("mqttServer") mqttServer: String): Builder

        fun build(): AppComponent
    

    fun inject(app: GeoAssistantApp)

然后在从Application 子类构造DaggerAppComponent 时提供模块的依赖关系(确保您使用specify the subclass name in AndroidManifest.xml):

class GeoAssistantApp : Application(), HasActivityInjector, HasSupportFragmentInjector 

    @Inject
    internal lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
    @Inject
    internal lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate() 
        super.onCreate()
        Log.i(GeoAssistantApp::class.java.simpleName, "Initializing DaggerAppComponent...")
        DaggerAppComponent.builder()
                // list of modules/dependencies of modules that are part of this component need to be created here too
                .application(this)
                .mqttServer(getString(R.string.mqtt_server))
                .build()
                .inject(this)
    

    override fun activityInjector(): AndroidInjector<Activity> 
        return activityDispatchingAndroidInjector
    

    override fun supportFragmentInjector(): AndroidInjector<Fragment> 
        return fragmentDispatchingAndroidInjector
    

请注意,support-v4 Fragment 与原生 Fragment 的使用可能是问题的根源。例如对于support-v4,你需要使用AndroidSupportInjectionModuleHasSupportFragmentInjector,而对于native,你需要使用AndroidInjectionModuleHasFragmentInjector

【讨论】:

【参考方案4】:

从 AppModule.class 中删除以下代码并重建项目

    @Provides
    @Singleton
    Application provideContext(SomeApplication application) 
        return application;
    

【讨论】:

感谢您的回答,想知道为什么会这样吗? Component.Builder 是 AppComponent 的自定义构建器。您为应用程序提供 BindsInstance。这就是 AppModule 知道在没有提供 Singleton 的情况下获取应用程序的方式。您使用自定义构建器,因此您不需要通过 AppModule 构造函数传递对象。 那是超级答案和@LEO 精湛的解释谢谢,但是现在我们如何才能获得应用程序实例。 获取任何提供的对象的方式相同 我很困惑,错误说我们需要添加一个setter,但你实际上删除了一个“provides”。在我看来,这不会解决问题,而是引入另一个问题,即不能 @Inject Application 因为 AppModule 不再是 @Provides Application 。但是你说这行得通,你能澄清你的答案来解释它是如何工作的(非直觉地)吗?谢谢。

以上是关于Dagger 2:@Component.Builder 缺少所需模块或组件的设置器:[appi.example.com.dagger.AppModule]`的主要内容,如果未能解决你的问题,请参考以下文章

Dagger 2 不注入 sharedPreference

Dagger 2 - 为啥我收到循环引用错误?

Dagger 2:@Component.Builder 缺少所需模块或组件的设置器:[appi.example.com.dagger.AppModule]`

Dagger 2 无法访问 Retrofit

Dagger 2 组件链依赖

Android 上的 Dagger 2,缺少错误消息