2

Ich entwickle eine Musik-Anwendung. Ich möchte das Bild des Künstlers von LastFM laden, also tue ich das so 1. Ich erstellte eine Klasse ArtistImageLoader extends BaseGlideUrlLoader. 2. In der getUrl Methode habe ich Retrofit2 verwendet, um die Bild-URL des Künstlers von LastFM über getArtistInfo Methode zu erhalten.Verwendung von Glide mit dagger2

Mein Problem ist, ich wusste nicht, wie man den Service von Retrofit injiziert, um die Anfrage in ArtistImageLoader zu machen. Ich habe diesen Weg gemacht, aber ich habe eine NOP-Ausnahme bekommen. lastFmService wurde nicht injiziert.

// 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() { 
     } 
    } 
} 

Können Sie mir helfen, es zu tun? Ich danke dir sehr!

Glide Version: 3.7.0

Integration Bibliotheken: OkHttp3 + Dagger2

Device/Android Version: Android Emulator + Asus 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

@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

Bitte geben Sie Ihre Module und Komponenten an. – Jacob

+0

@Jacob Ich habe die Module und Komponenten hinzugefügt –

+0

@KienViThanh konnten Sie das lösen? Ich habe das gleiche Problem. – Woppi

Antwort

0

Meine Vermutung ist, dass Ihr ArtistImageLoader in einer separaten Klasse definiert ist. Der Grund für dein Problem ist die Art, wie Dolch funktioniert. Es werden nur Felder mit der Adresse @Inject in die Klasse injiziert, die Sie als Parameter der inject-Methode angegeben haben. Daher wird nichts in Ihre ArtistImageLoader mit @Inject injiziert werden, sondern nur die annotierten Felder, die innerhalb Ihrer ArtistsFragment definiert sind.

Ich würde empfehlen, ein LastfmService-Feld mit der @Inject Annotation in Ihrem Fragment zu definieren und die Instanz an Ihre Glide LoaderFactory zu übergeben.Die Fabrik kann es den Instanzen des Laders bereitstellen. Es ist nicht die beste Lösung, aber da Sie es nicht direkt an die Instanzen übergeben können, scheint dies eine praktikable Lösung zu sein.

Ein anderer Ansatz wäre, Ihren Abhängigkeitsbaum in Ihrem benutzerdefinierten Application zu erstellen. Auf diese Weise können Sie von überall auf die Abhängigkeiten zugreifen, ohne vom Aktivitätslebenszyklus abhängig zu sein.

+0

Danke für Ihre Antwort. Aber ich möchte den 'ArtistImageLoader' in der GlideModule-Klasse registrieren anstatt ihn zu erstellen und eine Instanz in' ArtistFragment' zu setzen. Kann ich ein 'LastFmService'-Feld mit der '@ Inject'-Annotation im GlideModule definieren? Wie kann ich es tun? –

+0

Habe ich Sie richtig verstanden, dass die ArtistImageLoader-Instanz von einem separaten Modul bereitgestellt und in das ArtistFragment eingefügt werden soll? – Jacob

+0

Ich bin mir nicht sicher, wie ich die Instanz an die LoaderFactory übergeben soll. Weil das Fragment keine Instanz von LoaderFactory hatte. Es wurde nur in der Registermethode 'GlideModule' erstellt –

Verwandte Themen