How to address multiple API end points using Retrofit?

前端 未结 1 951
天命终不由人
天命终不由人 2021-02-09 05:09

In my Android project I am using the following Retrofit ApiModule for one API end point. Please note, I use Dagger for injecting dependencies.

1条回答
  •  [愿得一人]
    2021-02-09 05:45

    I guess you could work with Named annotations:

    @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));
        }
    }
    

    Now everywhere where you inject ProductsService you need to either annotate the dependency with @Named(PRODUCTS) or @Named(SUBSIDIARIES), depending on which variant you need. Of course instead of the @Named annotations you could also create your own, custom annotations and use them. See here under "Qualifiers".

    To flatten your module a bit you could move the creation of the RestAdapters into the provide*Service() methods and get rid of the provide*RestAdapter() methods. Unless you need the RestAdapters as a dependency outside of the module, of course.

    0 讨论(0)
提交回复
热议问题