2014-12-10 9 views
7

In meinem Android-Projekt verwende ich die folgenden RetrofitApiModule für einen API-Endpunkt. Bitte beachten Sie, dass ich Dagger zum Injizieren von Abhängigkeiten verwende.Wie können mehrere API-Endpunkte mit Retrofit behandelt werden?

@Module(
     complete = false, 
     library = true 
) 
public final class ApiModule { 

    public static final String PRODUCTS_BASE_URL = "https://products.com"; 

    @Provides 
    @Singleton 
    Endpoint provideEndpoint() { 
     return Endpoints.newFixedEndpoint(PRODUCTS_BASE_URL); 
    } 

    @Provides 
    @Singleton 
    ObjectMapper provideObjectMapper() { 
     ObjectMapper objectMapper = new ObjectMapper(); 
     objectMapper.setPropertyNamingStrategy(
      PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
     return objectMapper; 
    } 

    @Provides 
    @Singleton 
    RestAdapter provideRestAdapter(
     Endpoint endpoint, ObjectMapper objectMapper) { 
     return new RestAdapter.Builder() 
       .setLogLevel(RestAdapter.LogLevel.NONE) 
       .setEndpoint(endpoint) 
       .setConverter(new JacksonConverter(objectMapper)) 
       .build(); 
    } 

    @Provides 
    @Singleton 
    ProductsService provideProductsService(RestAdapter restAdapter) { 
     return restAdapter.create(ProductsService.class); 
    } 

} 

Nun ist es eine andere API (z "http://subsidiaries.com"), die ich mit kommunizieren möchten. Ist es möglich, die angegebene ApiModule zu verlängern, während die ObjectMapper und die RestAdapter wiederverwendet werden? Oder sollte ich es nicht verlängern? Ich habe bereits versucht, das Modul zu duplizieren. Aber das beinhaltet, dass ich die Endpoint, ObjectMapper und ... die RestAdapter eine private Konstruktor duplizieren muss - so kann ich nicht.

+1

können Sie nicht einen Konstruktor von 'ApiModule' machen und den Endpunkt dort übergeben und entsprechend mit IF Bedingung in allen Methoden kodieren? –

+0

@SweetWisher ツ Dependency Injection verwendet den ** Standardkonstruktor **. Das Übergeben von Parametern zur manuellen Bearbeitung verschiedener Fälle hilft daher hier nicht. – JJD

Antwort

4

Ich denke, Sie mit Named Anmerkungen funktionieren könnte:

@Module(
     complete = false, 
     library = true 
) 
public final class ApiModule { 

    public static final String PRODUCTS_BASE_URL = "https://products.com"; 
    public static final String SUBSIDIARIES_BASE_URL = "https://subsidiaries.com"; 

    public static final String PRODUCTS = "products"; 
    public static final String SUBSIDIARIES = "subsidiaries"; 

    @Provides 
    @Singleton 
    @Named(PRODUCTS) 
    Endpoint provideProductsEndpoint() { 
     return Endpoints.newFixedEndpoint(PRODUCTS_BASE_URL); 
    } 

    @Provides 
    @Singleton 
    @Named(SUBSIDIARIES) 
    Endpoint provideSubsidiariesEndpoint() { 
     return Endpoints.newFixedEndpoint(SUBSIDIARIES_BASE_URL); 
    } 

    @Provides 
    @Singleton 
    ObjectMapper provideObjectMapper() { 
     ObjectMapper objectMapper = new ObjectMapper(); 
     objectMapper.setPropertyNamingStrategy(
      PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
     return objectMapper; 
    } 

    @Provides 
    @Singleton 
    @Named(PRODUCTS) 
    RestAdapter provideProductsRestAdapter(@Named(PRODUCTS) Endpoint endpoint, ObjectMapper objectMapper) { 
     return newRestAdapterBuilder(objectMapper) 
       .setEndpoint(endpoint) 
       .build(); 
    } 

    @Provides 
    @Singleton 
    @Named(SUBSIDIARIES) 
    RestAdapter provideSubsidiariesRestAdapter(@Named(SUBSIDIARIES) Endpoint endpoint, ObjectMapper objectMapper) { 
     return newRestAdapterBuilder(objectMapper) 
       .setEndpoint(endpoint) 
       .build(); 
    } 

    @Provides 
    @Singleton 
    @Named(PRODUCTS) 
    ProductsService provideProductsService(@Named(PRODUCTS) RestAdapter restAdapter) { 
     return restAdapter.create(ProductsService.class); 
    } 

    @Provides 
    @Singleton 
    @Named(SUBSIDIARIES) 
    ProductsService provideSubsidiariesService(@Named(SUBSIDIARIES) RestAdapter restAdapter) { 
     return restAdapter.create(ProductsService.class); 
    } 

    private RestAdapter.Builder newRestAdapterBuilder(ObjectMapper objectMapper) { 
     return new RestAdapter.Builder() 
         .setLogLevel(RestAdapter.LogLevel.NONE) 
         .setConverter(new JacksonConverter(objectMapper)); 
    } 
} 

Jetzt überall, wo Sie injizieren ProductsService Sie müssen entweder die Abhängigkeit mit @Named(PRODUCTS) oder @Named(SUBSIDIARIES) mit Anmerkungen versehen, je nachdem, welche Variante Sie benötigen. Natürlich können Sie anstelle der @Named Annotationen auch eigene Annotationen erstellen und diese verwenden. Siehe here unter "Qualifier".

Um Ihr Modul ein wenig flacher zu machen, könnten Sie die Erstellung der RestAdapters in die provide*Service() Methoden verschieben und die provide*RestAdapter() Methoden loswerden. Es sei denn, Sie benötigen die RestAdapters natürlich als eine Abhängigkeit außerhalb des Moduls.

Verwandte Themen