Dagger2について分かってなかったこと
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var viewModel: MainViewModel
}
MainActivityにviewModel
を保持させてくて、@Inject
アノテーションを付けてあげれば、インスタンスを注入してくれてる。
インスタンス注入するには、以下のような準備は必要です。
下記のようにActivityModule
とAppComonent
を定義し、ActivityModule
をAppComponent
の@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.xml
にApp
を指定する必要がありますし、
<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
とみなしてくれるかどうかが、怪しくなってきました。。今度調べます。。
いまは自分の中でここまでわかったということで、この記事は締めたいと思います。
- Previous
Kotlin Enum - Next
Kotlinプロジェクトで「Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter favicon」というエラーが出たときの対処法