我正在开发音乐应用程序。我想从LastFM加载艺术家的图像,所以我这样做
1.我创建了一个班级ArtistImageLoader extends BaseGlideUrlLoader
。
2.在getUrl
方法中,我使用retrofit2通过getArtistInfo方法从LastFM获取艺术家的图像网址。
我的问题是我不知道如何注入改造服务以在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() {
}
}
}
你能帮帮我吗?非常感谢你!
滑翔版: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;
}
}
答案 0 :(得分:0)
我的假设是您的ArtistImageLoader是在一个单独的类中定义的。你的问题的原因是匕首的工作方式。它只会在您指定为注入方法参数的类上注入带有@Inject
注释的字段。因此,ArtistImageLoader
注释@Inject
内的任何内容都不会被注入,只会注入已在ArtistsFragment
内定义的带注释字段。
我建议在片段中定义带有@Inject
注释的LastfmService字段,并将实例传递给Glide LoaderFactory。工厂可以将其提供给装载机的实例。它不是最好的解决方案,但由于你不能直接将它传递给实例,这似乎是可行的解决方法。
另一种方法是在自定义Application
中构建依赖关系树。这允许您从任何地方访问依赖项,而不依赖于活动生命周期。