2

음악 응용 프로그램을 개발 중입니다. LastFM에서 아티스트의 이미지를로드하고 싶습니다. 이렇게하면됩니다. 1. 클래스 ArtistImageLoader extends BaseGlideUrlLoader을 만들었습니다. 2. getUrl 방법에서 retrofit2를 사용하여 LastFM에서 아티스트의 이미지 URL을 getArtistInfo 방법으로 가져 왔습니다.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() { 
     } 
    } 
} 

당신은 내가 그것을 어떻게 도와 드릴까요? 정말 고맙습니다!

글라이드 버전 : 3.7.0

통합 라이브러리 : OkHttp3 + Dagger2

장치/안드로이드 버전 : 안드로이드 에뮬레이터 + 아수스 zenfone 5

EDIT 1

ActivityComponent.ja VA

@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

,451,515,
@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으로 주석 된 필드 만 삽입합니다. 따라서 안에 @Inject으로 주석 된 것이 없으며, ArtistsFragment 안에 정의 된 주석이 달린 필드 만 주입됩니다.

조각에 @Inject 주석이있는 LastfmService 필드를 정의하고 인스턴스를 Glide LoaderFactory로 전달하는 것이 좋습니다.팩토리는 로더의 인스턴스에이를 제공 할 수 있습니다. 가장 좋은 솔루션은 아니지만 직접 인스턴스에 전달할 수 없기 때문에 가능한 해결 방법 인 것처럼 보입니다.

또 다른 방법은 사용자 지정 Application 내부에 종속성 트리를 작성하는 것입니다. 따라서 활동 라이프 사이클에 의존하지 않고도 어디에서나 종속성에 액세스 할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 그러나 나는'ArtistImageLoader'를'ArtistFragment'에서 인스턴스를 생성하고 설정하는 대신 GlideModule 클래스에 등록하려고합니다. GlideModule에서'@Inject' 어노테이션으로'LastFmService' 필드를 정의 할 수 있습니까? 내가 어떻게 해? –

+0

ArtistImageLoader 인스턴스를 별도의 모듈에서 제공하고 ArtistFragment에 삽입하고 싶다고 올바르게 이해 했습니까? – Jacob

+0

저는 인스턴스를 LoaderFactory에 전달하는 방법을 모르겠습니다. 왜냐하면 조각에는 LoaderFactory의 인스턴스가 없기 때문입니다. 'GlideModule'의 등록 메소드에서 막 생성했습니다. –