bumptech / glide

An image loading and caching library for Android focused on smooth scrolling
https://bumptech.github.io/glide/
Other
34.64k stars 6.12k forks source link

How can i use Glide with dagger2 #1533

Closed kienvtqhi closed 6 years ago

kienvtqhi commented 8 years ago

Hello

Glide Version: 3.7.0

Integration libraries: OkHttp3 + Dagger2

Device/Android Version: Android Emulator + Asus zenfone 5

Issue details / Repro steps / Use case background: I am developing a music application. I want to load artist's image from LastFM so i do this this way

  1. I created a class ArtistImageLoader extends BaseGlideUrlLoader.
  2. In the getUrl method i used retrofit2 to get the artist's image url from LastFM via getArtistInfo method.

My problem is i didn't know how to inject the service of retrofit to make the request in ArtistImageLoader. I did this way but i got a NOP exception. lastFmService wasn't be not injected.

Glide load line / GlideModule (if any) / list Adapter code (if any):

// GlideModule
glide.register(MLocalArtist.class, InputStream.class, new ArtistImageLoader.Factory());

// Use it in onCreate method of ArtistsFragment
DaggerLastFmComponent.builder().activityModule(new ActivityModule(getActivity()))
                .netComponent(getNetComponent())
                .build().inject(this);

// use this code in onBindViewHolder method of artists recycler adapter
Glide.with(getContext())
                .from(MLocalArtist.class)
                .load(localArtist)
                .into(localArtistViewHolder.ivArtwork);

ArtistImageLoader

public class ArtistImageLoader extends BaseGlideUrlLoader<MLocalArtist> {

    @Inject
    LastfmService lastfmService;

    public ArtistImageLoader(Context context) {
        super(context);
    }

    @Override
    protected String getUrl(MLocalArtist model, int width, int height) {
        Call<List<MArtist>> call = lastfmService.getArtistInfo(model.artistName);
        try {
            List<MArtist> artists = call.execute().body();
            if (artists != null && artists.size() > 0) {
                Timber.e(artists.get(0).toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static class Factory implements ModelLoaderFactory<MLocalArtist, InputStream> {
        @Override public ModelLoader<MLocalArtist, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new ArtistImageLoader(context);
        }
        @Override public void teardown() {
        }
    }
}

Can you help me to do it? Thank you so much!

TWiStErRob commented 8 years ago

I'm not sure how dagger would know to set the loader's field, since the activity has no reference to it and you've created the object manually. I think you need to do the injection earlier, either in Factory.build or in the GlideModule.

One thing that's really important with your attempt is that getUrl is called on the UI thread! Check out #634 (and related) to see how to do a double dispatch in the background.

kienvtqhi commented 8 years ago

@TWiStErRob How could I do the injection in Factory.build or in my custom GlideModule?

TWiStErRob commented 8 years ago

The loader/factory is application wide so you should be creating a component in the Application setup, not in every activity. You can control the order because Glide will be only initialised with the module on first interaction, so you can do the Dagger setup first. If you have multiple netComponents you may want to consider creating multiple custom models for them.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.