【问题标题】:How to use Glide with dagger2如何使用 Glide 与 dagger2
【发布时间】:2017-02-28 21:19:09
【问题描述】:

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

我的问题是我不知道如何注入改造服务以在ArtistImageLoader 中提出请求。我这样做了,但我得到了一个 NOP 异常。 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() {
        }
    }
}

你能帮我做吗?非常感谢!

Glide 版本:3.7.0

集成库:OkHttp3 + Dagger2

设备/Android 版本:Android Emulator + Asus 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;
    }
}

【问题讨论】:

  • 请提供您的模块和组件。
  • @Jacob 我添加了模块和组件
  • @KienViThanh 你能解决这个问题吗?我也有同样的问题。

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


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的回答。但我想将ArtistImageLoader 注册到 GlideModule 类中,而不是在ArtistFragment 中创建和设置一个实例。我可以在 GlideModule 中使用 @Inject 注释定义一个 LastFmService 字段吗?我该怎么做?
  • 我是否理解正确,您希望 ArtistImageLoader 实例由单独的模块提供并注入 ArtistFragment ?
  • 我只是不确定如何将实例传递给 LoaderFactory。因为片段没有任何 LoaderFactory 实例。它只是在GlideModule的注册方法中创建的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 2020-01-20
  • 2018-10-25
  • 1970-01-01
  • 2019-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多