Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to inject OkHttpClient instance #2002

Open
b95505017 opened this issue Jun 3, 2017 · 19 comments
Open

How to inject OkHttpClient instance #2002

b95505017 opened this issue Jun 3, 2017 · 19 comments

Comments

@b95505017
Copy link
Contributor

b95505017 commented Jun 3, 2017

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.

@gajicm93
Copy link

Glide.with(context).getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(CLIENT));

@TWiStErRob
Copy link
Collaborator

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.

@b95505017
Copy link
Contributor Author

I know the getRegistry().replace(...) way, but I want to use the default OkHttpLibraryGlideModule with my application OkHttpClient instance injection.

@TWiStErRob
Copy link
Collaborator

TWiStErRob commented Jun 13, 2017

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.

@sjudd
Copy link
Collaborator

sjudd commented Jun 15, 2017

Yes getRegistry() will probably start throwing an exception if it's modified outside of a GlideModule in the near future.

@b95505017
Copy link
Contributor Author

@sjudd So is there a recommend way to share my OkHttpClient instance with Glide 4?

@sjudd
Copy link
Collaborator

sjudd commented Jun 15, 2017

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

@dptsolutions
Copy link

dptsolutions commented Jul 2, 2017

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.

@TWiStErRob
Copy link
Collaborator

@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.

@ar-g
Copy link

ar-g commented Sep 15, 2017

I completely agree with @dptsolutions that setting up Glide this way is not obvious at all.

@tata8k
Copy link

tata8k commented Feb 3, 2018

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

@birdeveloper
Copy link

I solved the problem: https://stackoverflow.com/a/49569958/12283105

@dawidhyzy
Copy link

Is there any way to use constructor injection?

@ahulyk
Copy link

ahulyk commented Mar 6, 2020

Please use the following solution:
https://gist.github.com/ahulyk/149aa35b228f0711bc530cb6dcc0e6ce

@gmazzo
Copy link

gmazzo commented Mar 18, 2020

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"

@ahulyk
Copy link

ahulyk commented Mar 18, 2020

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"

We have access to context in glide module:
registerComponents(context: Context, glide: Glide, registry: Registry)

@bobziuchkovski
Copy link

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));
    }
}

@cyclops-cosfes
Copy link

cyclops-cosfes commented Sep 3, 2020

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>
}

@newmanw
Copy link

newmanw commented Sep 1, 2023

Anyone have a working example using hilt 2.41+?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests