Dagger2でProvidesアノテーションつけてないのに、なぜフィールド注入されるのか

Posted by on Sat, Oct 21, 2017

Dagger2について分かってなかったこと

class MainActivity : DaggerAppCompatActivity() {
    @Inject
    lateinit var viewModel: MainViewModel
}

MainActivityにviewModelを保持させてくて、@Injectアノテーションを付けてあげれば、インスタンスを注入してくれてる。

インスタンス注入するには、以下のような準備は必要です。

下記のようにActivityModuleAppComonentを定義し、ActivityModuleAppComponent@Component(modules=ActivityModule::class)に指定します。

@Singleton
@Component(modules = arrayOf(
        AndroidSupportInjectionModule::class,
        AppModule::class,
        ActivityModule::class
    )
)
interface AppComponent : AndroidInjector<App> {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: App): Builder

        fun build():AppComponent

    }
}
@Module
abstract class ActivityModule {

    @ActivityScope
    @ContributesAndroidInjector
    internal abstract fun contributeMainActivity(): MainActivity

}

ActivityScopeも定義が必要だし、

@Scope
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class ActivityScope

AndroidManifest.xmlAppを指定する必要がありますし、

<application
        android:name=".App"

そもそもAppは、Applicationを継承したクラスで、

open class App : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return  DaggerAppComponent.builder().application(this).build()
    }
}

のように定義されてます。最後にMainViewModel

@ActivityScope
class MainViewModel @Inject
constructor() : BaseObservable() {

    fun onClickButton(view: View) {
        Log.d("MainViewModel", "onclick")
    }
}

のような感じで定義しています。

また、Activityとは独立したGithubClientクラスを作成しているのですが、それをInjectしたい場合、

@Module
class AppModule() {
    @Singleton
    @Provides
    fun provideGithubApi(client: OkHttpClient, moshi: Moshi): GithubApi {
        return Retrofit.Builder()
                .client(client)
                .baseUrl(BuildConfig.BASE_API_URL)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .build()
                .create(GithubApi::class.java)
    }
}

のように@Providesアノテーションを付ければ、インスタンスを提供できると理解していました。

では、MainViewModel@Providesアノテーションをつけないとインスタン注入出来ないんじゃないの?と思いながらも、実際注入できてるので、なんでかな?というのがずっと気になってました。

答えはMainActivityのSubComponentだから

と書こうとしたのですが、その根拠をよくよく調べてみると、いまは分からなくなってきましたので、たぶん、にしておきます。

おそらく下記ページのSubcomponentの項目を読めばなんとなくわかると思うのですが。。

https://google.github.io/dagger/api/latest/dagger/Component.html

とくに分からなくなったのは、

class MainActivity : DaggerAppCompatActivity() {
    @Inject
    lateinit var viewModel: MainViewModel
}

と、@Injectしただけで、Subcomponentとみなしてくれるかどうかが、怪しくなってきました。。今度調べます。。

いまは自分の中でここまでわかったということで、この記事は締めたいと思います。



comments powered by Disqus