如何在dagger2中使用Glide

时间:2016-10-19 09:52:35

标签: dependency-injection retrofit2 dagger-2 android-glide okhttp3

我正在开发音乐应用程序。我想从LastFM加载艺术家的图像,所以我这样做 1.我创建了一个班级ArtistImageLoader extends BaseGlideUrlLoader。 2.在getUrl方法中,我使用retrofit2通过getArtistInfo方法从LastFM获取艺术家的图像网址。

我的问题是我不知道如何注入改造服务以在ArtistImageLoader中发出请求。我这样做但我得到了一个N​​OP例外。 lastFmService没有被注射。

// 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() {
        }
    }
}
你能帮帮我吗?非常感谢你!

滑翔版:3.7.0

集成库:OkHttp3 + Dagger2

设备/ Android版:Android模拟器+华硕zenfone 5

编辑1

ActivityComponent.java

@PerActivity
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    Context context();
}

AppComponent.java

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    App app();
}

NetComponent.java

@Singleton
@Component(modules = {NetModule.class, AppModule.class})
public interface NetComponent {
    @Named("chartSoundCloud")
    Retrofit getSoundcloudChartRetrofit();

    @Named("searchSoundCloud")
    Retrofit getSoundcloudSearchRetrofit();

    @Named("lastFM")
    Retrofit getLastFmRetrofit();
}

LastFmComponent.java

@PerActivity
@Component(dependencies = NetComponent.class, modules = {LastFmModule.class, ActivityModule.class})
public interface LastFmComponent extends ActivityComponent {
    void inject(ArtistsFragment artistsFragment);
}

ActivityModule.java

@Module
public class ActivityModule {
    private final Context mContext;

    public ActivityModule(Context mContext) {
        this.mContext = mContext;
    }

    @Provides
    @PerActivity
    Context provideActivityContext() {
        return mContext;
    }
}

AppModule.java

@Module
public class AppModule {
    private App app;

    public AppModule(App app){
        this.app = app;
    }

    @Singleton
    @Provides
    App provideApplication() {
        return app;
    }

    @Singleton
    @Provides @Named("applicationContext")
    Context provideApplicationContext(){
        return app;
    }
}

LastFmModule.java

@Module
public class LastFmModule {

    @Provides
    @PerActivity
    LastfmService provideLastFmService(@Named("lastFM") Retrofit retrofit) {
        return retrofit.create(LastfmService.class);
    }

}

NetModule.java

@Module
public class NetModule {
    static final int DISK_CACHE_SIZE = (int) MEGABYTES.toBytes(50);

    @Provides
    @Singleton
    Cache provideOkHttpCache(@Named("applicationContext") Context application) {
        Cache cache = new Cache(application.getCacheDir(), DISK_CACHE_SIZE);
        return cache;
    }

    @Provides
    @Singleton
    ScdClientIdInterceptor provideScdClientIdInterceptor() {
        return new ScdClientIdInterceptor();
    }

    @Provides
    @Singleton
    LastFMInterceptor provideLastFmInterceptor() {
        return new LastFMInterceptor();
    }

    @Provides
    @Singleton
    HttpLoggingInterceptor provideHttpLoggingInterceptor() {
        return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
    }

    @Provides
    @Singleton
    @Named("soundcloud-Http")
    OkHttpClient provideOkHttpSoundCloudClient(Cache cache,  ScdClientIdInterceptor clientIdInterceptor, HttpLoggingInterceptor httpLoggingInterceptor) {
        return createOkHttpClient(cache, clientIdInterceptor, httpLoggingInterceptor);
    }

    @Provides
    @Singleton
    @Named("lastFM-Http")
    OkHttpClient provideOkHttpLastFmClient(Cache cache, LastFMInterceptor clientIdInterceptor, HttpLoggingInterceptor httpLoggingInterceptor) {
        return createOkHttpClient(cache, clientIdInterceptor, httpLoggingInterceptor);
    }

    private OkHttpClient createOkHttpClient(Cache cache,  Interceptor clientIdInterceptor, HttpLoggingInterceptor httpLoggingInterceptor) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cache(cache)
                .addInterceptor(clientIdInterceptor)
                .addInterceptor(httpLoggingInterceptor)
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();

        return okHttpClient;
    }

    @Provides
    @Singleton
    Gson provideGson() {
        return GsonFactory.create();
    }

    @Provides
    @Singleton
    @Named("searchSoundCloud")
    Retrofit provideSearchSoundCloudRetrofit(Gson gson, @Named("soundcloud-Http") OkHttpClient okHttpClient) {
        Retrofit searchRetrofit = new Retrofit.Builder()
                .baseUrl(Constants.BASE_SOUNDCLOUD_API_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return searchRetrofit;
    }

    @Provides
    @Singleton
    @Named("chartSoundCloud")
    Retrofit provideChartSoundCloudRetrofit(Gson gson, @Named("soundcloud-Http") OkHttpClient okHttpClient) {
        Retrofit chartRetrofit = new Retrofit.Builder()
                .baseUrl(Constants.BASE_SOUNDCLOUD_API_V2_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return chartRetrofit;
    }

    @Provides
    @Singleton
    @Named("lastFM")
    Retrofit provideLastFmRetrofit(Gson gson, @Named("lastFM-Http") OkHttpClient okHttpClient) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constants.LASTFM_API_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return retrofit;
    }
}

1 个答案:

答案 0 :(得分:0)

我的假设是您的ArtistImageLoader是在一个单独的类中定义的。你的问题的原因是匕首的工作方式。它只会在您指定为注入方法参数的类上注入带有@Inject注释的字段。因此,ArtistImageLoader注释@Inject内的任何内容都不会被注入,只会注入已在ArtistsFragment内定义的带注释字段。

我建议在片段中定义带有@Inject注释的LastfmService字段,并将实例传递给Glide LoaderFactory。工厂可以将其提供给装载机的实例。它不是最好的解决方案,但由于你不能直接将它传递给实例,这似乎是可行的解决方法。

另一种方法是在自定义Application中构建依赖关系树。这允许您从任何地方访问依赖项,而不依赖于活动生命周期。