前提
既にDagger2によるDIをかっちり組んでOkHttpClientをInjectしているプロジェクトで、新たにGlide v4を導入する場合。
参考にしたコード
How to inject OkHttpClient instance · Issue #2002 · bumptech/glide
サンプルコード
issueではApplicationをSingletonにしてインスタンスを参照するような解決方法でしたが、どうせregisterComponentsでapplicationContextを突っ込むならそこでInjectすればよかろうと考えました。
AppGlideModule用にSubcomonentを定義し、DaggerApplication派生のApplicationクラスにinjectメソッドを追加しました。
新たに追加する分
AppGlideModuleはregisterComponentsに前述の処理を加えた以外はセオリー通りです。
AppGlideModule
@GlideModule(glideName = "CustomGlideApp")
class CustomAppGlideModule : AppGlideModule() {
@Inject
lateinit var okHttpClient: OkHttpClient
override fun isManifestParsingEnabled() = false
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
super.registerComponents(context, glide, registry)
(context.applicationContext as App).inject(this)
glide.registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(okHttpClient))
}
}
Subcomponent
SubcomponentにはBuilderを定義しています。
@Subcomponent
interface GlideComponent {
fun inject(appGlideModule: CustomAppGlideModule)
@Subcomponent.Builder
interface Builder {
fun build(): GlideComponent
}
}
既存のものに変更する分
AppModule
AppModuleはsubcomponentsアノテーションに先述のSubcomponentを追加するだけです。
@Module(subcomponents = [GlideComponent::class])
internal object AppModule {
// 以下は既存のものそのままなので略
}
AppComponent
AppComponentにはSubcomponentのBuilderを生成するメソッドを追加します。
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
MainActivityBuilder::class,
ViewModelModule::class
])
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
override fun inject(application: App)
// 以下新しく追加
fun glideComponentBuilder(): GlideComponent.Builder
}
Application
ApplicationはInjectメソッドを追加します。
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder()
.application(this)
.build()
}
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
// 以下新しく追加
fun inject(appGlideModule: CustomAppGlideModule) {
(applicationInjector() as AppComponent).glideComponentBuilder().build().inject(appGlideModule)
}
}
後はViewで利用するだけです。
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MainViewModel
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
CustomGlideApp.with(this)
.load("https://qiita-image-store.s3.amazonaws.com/0/21354/profile-images/1473683312")
.into(binding.image)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(MainViewModel::class.java)
}
}
サンプルではQiitaの私のアイコンを読み込ませました。不気味です。