glide
glide copied to clipboard
How to inject OkHttpClient instance
According to OkHttp jdoc:
OkHttpClients should be shared
I notice that the OkHttp integration module generate a OkHttpClient internal instance. It would be better to allow us inject the singleton OkHttpClient within our application.
Glide.with(context).getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(CLIENT));
See also: http://bumptech.github.io/glide/doc/configuration.html#applications
It's probably better to have a GlideModule then statically messing with the registry somewhere .with(context) may imply expensive initialization that you're not expecting at that point.
I know the getRegistry().replace(...) way, but I want to use the default OkHttpLibraryGlideModule with my application OkHttpClient instance injection.
You can't use the default integration Glide module, as there's no way to propagate your custom client to that module. That's why you need to write your own App module, exclude the library module and register the factory yourself with your custom client.
Yes getRegistry() will probably start throwing an exception if it's modified outside of a GlideModule in the near future.
@sjudd So is there a recommend way to share my OkHttpClient instance with Glide 4?
You can pass it into Glide in an AppGlideModule or LibraryGlideModule. Accessing it in the Module will require either dependency injection or holding your client in a singleton somewhere.
For modules, see http://bumptech.github.io/glide/doc/configuration.html#appglidemodule
After going through the links and everyone's comments here, I've come up with this example that should allow me to use the OkHttp3 integration library, exclude the @GlideModule that comes with the integration library, and provide my own OkHttpClient instance from my Dagger 2 ApplicationComponent - Glide4OkHttp3Dagger2Module.java. Perhaps it could be an example for the documentation?
That said, this being my first time using Glide, this method of getting the component into Glide seems clunky. I kind of wish I could just intialize a @Singleton scoped GlideApp instance in my ApplicationModule and just inject that baby through Dagger 2, like anything else I need.
@dptsolutions that looks ok to me.
Note that you cannot have a @Provides @Singleton GlideApp glide() because GlideApp doesn't have instance methods. You'll need @Provides @FragmentScope GlideRequests glide(Fragment frag) { return GlideApp.with(frag); }.
In your GlideModule you can try to make it a bit nicer with something like:
public interface ApplicationComponent {
void inject(MyAppGlideModule glide);
}
public class MyAppGlideModule extends AppGlideModule {
@Inject OkHttpClient client;
public MyAppGlideModule() {
MyApplication.getInstance().getApplicationComponent().inject(this);
}
... new OkHttpUrlLoader.Factory(client)
but your current approach is just as valid: the component interface is there so that you can pull objects out of the dependency graph.
I completely agree with @dptsolutions that setting up Glide this way is not obvious at all.
This is my project demo
AppComponent
@Singleton
@Component(modules = [(AppModule::class)])
interface AppComponent : AndroidInjector<App> {
fun glideComponentBuilder(): GlideComponent.Builder
@Component.Builder
abstract class Builder : AndroidInjector.Builder<App>()
}
@Singleton
@Module(includes = [(AndroidSupportInjectionModule::class), (AppBinder::class)],
subcomponents = [(GlideComponent::class)])
class AppModule {
@Singleton
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
Glide Config
@Excludes(OkHttpLibraryGlideModule::class)
@GlideModule
class NewOkHttpLibraryGlideModule : AppGlideModule() {
@Inject
lateinit var okHttpClient: OkHttpClient
init {
App.instance!!.appComponent()
.glideComponentBuilder()
.glideModule(GlideDaggerModule())
.build()
.inject(this)
}
override fun isManifestParsingEnabled() = false
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
super.registerComponents(context, glide, registry)
registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(okHttpClient))
}
}
@Subcomponent(modules = [(GlideDaggerModule::class)])
interface GlideComponent {
fun inject(newOkHttpLibraryGlideModule: NewOkHttpLibraryGlideModule)
@Subcomponent.Builder
interface Builder {
fun glideModule(glideModule: GlideDaggerModule): Builder
fun build(): GlideComponent
}
}
@Module
class GlideDaggerModule
I solved the problem: https://stackoverflow.com/a/49569958/12283105
Is there any way to use constructor injection?
Please use the following solution: https://gist.github.com/ahulyk/149aa35b228f0711bc530cb6dcc0e6ce
Please use the following solution: https://gist.github.com/ahulyk/149aa35b228f0711bc530cb6dcc0e6ce
Accessing the Application context is a bit hacky and won't work for libraries modules. Is there any way to provide instances of modules by hand? I mean, to disable the "auto-discovery"
Please use the following solution: https://gist.github.com/ahulyk/149aa35b228f0711bc530cb6dcc0e6ce
Accessing the
Applicationcontext is a bit hacky and won't work for libraries modules. Is there any way to provide instances of modules by hand? I mean, to disable the "auto-discovery"
We have access to context in glide module:
registerComponents(context: Context, glide: Glide, registry: Registry)
Just wanted to add an example for any folks who are using Hilt rather than using dagger directly.
Hilt Module:
@Module
@InstallIn(ApplicationComponent.class)
public final class MyAppHiltModule {
@Provides
static OkHttpClient provideOkHttpClient(/* insert injected dependencies for the okhttp client, if any*/) {
return new OkHttpClient.Builder()
// <insert other options>
.build();
}
}
Glide Module:
@GlideModule
@Excludes(OkHttpLibraryGlideModule.class)
public final class MyAppGlideModule extends AppGlideModule {
@EntryPoint
@InstallIn(ApplicationComponent.class)
interface MyAppGlideModuleEntryPoint {
OkHttpClient defaultOkHttpClient();
}
@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
Context appContext = context.getApplicationContext();
MyAppGlideModuleEntryPoint entryPoint =
EntryPointAccessors.fromApplication(appContext, MyAppGlideModuleEntryPoint.class);
OkHttpClient client = entryPoint.defaultOkHttpClient();
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
}
}
Dagger.
Glide Module:
@GlideModule
@Excludes(OkHttpLibraryGlideModule::class)
class AppGlideModule: com.bumptech.glide.module.AppGlideModule() {
@Inject
lateinit var okHttpClient: OkHttpClient
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
super.registerComponents(context, glide, registry)
(context.applicationContext as Application).androidInjector().inject(this)
var factory = OkHttpUrlLoader.Factory(okHttpClient)
registry.replace(GlideUrl::class.java, InputStream::class.java, factory)
}
}
Dagger Module:
@Module
abstract class GlideModule {
@ContributesAndroidInjector
abstract fun provideAppGlideModule(): AppGlideModule
}
Application Component:
@Singleton
@Component(
modules = [
AndroidSupportInjectionModule::class,
GlideModule::class,
...
]
)
interface ApplicationComponent : AndroidInjector<Application> {
@Component.Factory
interface Factory : AndroidInjector.Factory<Application>
}
Anyone have a working example using hilt 2.41+?