2

Я занимаюсь разработкой музыкального приложения. Я хочу загрузить образ художника из LastFM, поэтому я делаю это так 1. Я создал класс ArtistImageLoader extends BaseGlideUrlLoader. 2. В методе getUrl я использовал retrofit2, чтобы получить URL-адрес изображения художника от LastFM по методу getArtistInfo.Как использовать Glide с dagger2

Моя проблема в том, что я не знал, как ввести услугу модификации, чтобы сделать запрос в 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

EDIT 1

АктивностьComponent.ja ва

@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

Просьба представить ваши модули и компоненты. – Jacob

+0

@Jacob Я добавил модули и компоненты –

+0

@KienViThanh, могли ли вы решить это? У меня такая же проблема. – Woppi

ответ

0

Мое предположение, что ваш ArtistImageLoader определяется в отдельном классе. Причина вашей проблемы заключается в том, как работает кинжал. Он вводит только поля, аннотированные @Inject в классе, который вы указали как параметр метода инъекции. Поэтому ничто внутри вашего ArtistImageLoader с аннотацией @Inject не будет введено, а только аннотированные поля, которые определены внутри вашего ArtistsFragment.

Я бы рекомендовал определить поле LastfmService с аннотацией @Inject в вашем фрагменте и передать экземпляр вашему Glide LoaderFactory.Завод может предоставить его экземплярам погрузчика. Это не самое приятное решение, но поскольку вы не можете напрямую передать его экземплярам, ​​это кажется жизнеспособным решением.

Другим подходом было бы построить дерево зависимостей внутри вашего настраиваемого Application. Это позволяет вам обращаться к зависимостям из любого места, не завися от жизненного цикла активности.

+0

Спасибо за ваш ответ. Но я хочу зарегистрировать «ArtistImageLoader» в классе GlideModule вместо создания и установки экземпляра в «ArtistFragment». Могу ли я определить поле «LastFmService» с аннотацией «@ Inject» в GlideModule? Как мне это сделать? –

+0

Правильно ли я понял вас, что вы хотите, чтобы экземпляр ArtistImageLoader предоставлялся отдельным модулем и вводился в ArtistFragment? – Jacob

+0

Я просто не уверен, как передать экземпляр в LoaderFactory. Поскольку у фрагмента не было экземпляра LoaderFactory. Он просто создан в регистровом методе 'GlideModule' –

 Смежные вопросы

  • Нет связанных вопросов^_^