web-dev-qa-db-ja.com

Dagger 2:@ Component.Builderに必要なモジュールまたはコンポーネントのセッターがありません:[appi.example.com.dagger.AppModule] `

新しい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);
  }
}
37
Leonardo Deleon

AppModule.classから以下のコードを削除し、プロジェクトを再構築します

    @Provides
    @Singleton
    Application provideContext(SomeApplication application) {
        return application;
    }
42
Gnanendra Kumar

これにより、@BindsInstanceの使用と@Provides Applicationの削除、 Dagger 2 Component Builder の説明がやや明確になったと思います。

@BindsInstance何?

定義は次のとおりです。

インスタンスをコンポーネント内の特定のタイプにバインドできるようにするコンポーネントビルダーまたはサブコンポーネントビルダーのメソッドをマークします。 — source

なんだ?分かりませんか????

使用するタイミングの簡単なヒントを次に示します。

@BindsInstanceメソッドは、コンストラクター引数を使用して@Moduleを作成し、それらの値をすぐに提供するよりも優先する必要があります。 — source

私はSpring Bootから来ました。Dagger2は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)
}

次に、DaggerAppComponentサブクラスからApplicationを構築するときにモジュールの依存関係を指定します(必ず、 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-v4FragmentとネイティブFragmentの使用法が問題の原因になる可能性があることに注意してください。例えばsupport-v4の場合、AndroidSupportInjectionModuleHasSupportFragmentInjectorを使用する必要がありますが、ネイティブでは、AndroidInjectionModuleHasFragmentInjectorを使用する必要があります。

14
Hendy Irawan

私の場合、オブジェクトモジュールを使用していたため、@ JvmStaticで注釈を付ける必要がありました

7
Federico Torres