在我的Android项目中,我将以下Retrofit ApiModule用于一个 API端点。请注意,我使用Dagger注入(inject)依赖项。

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

}

现在,我想与另一个API (例如"http://subsidiaries.com")一起。可以在重用ApiModuleObjectMapper的同时扩展给定的RestAdapter吗?还是我不应该扩展它?我已经尝试复制该模块。但这涉及到我必须重复EndpointObjectMapper和...。RestAdapter具有私有(private)构造函数-因此我不能。

最佳答案

我猜你可以使用Named注释:

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

现在,在所有需要注入(inject)ProductsService的地方,都需要使用@Named(PRODUCTS)@Named(SUBSIDIARIES)注释依赖项,具体取决于所需的变体。当然,除了@Named批注之外,您还可以创建自己的自定义批注并使用它们。请参见“限定符”下的here

为了稍微扁平化您的模块,您可以将RestAdapters的创建移到provide*Service()方法中,并摆脱provide*RestAdapter()方法。当然,除非您需要RestAdapters作为模块外部的依赖项。

08-28 19:15