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 在您的 AppModule
和 NetModule
构建器方法上有一个 @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,你需要使用AndroidSupportInjectionModule
,HasSupportFragmentInjector
,而对于native,你需要使用AndroidInjectionModule
,HasFragmentInjector
。
【讨论】:
【参考方案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:@Component.Builder 缺少所需模块或组件的设置器:[appi.example.com.dagger.AppModule]`