Подтвердить что ты не робот

Кинжал 2, вводящий несколько экземпляров одного и того же типа объекта

Фон

Я конвертирую свое приложение в архитектуру MVP и обнаружил, что Dagger 2 полезен для приведения зависимостей, когда это необходимо. Моему приложению нужно общаться с двумя веб-авиями (мой собственный и сторонний api). Могут быть случаи, когда запросы на мой собственный api и сторонний api могут срабатывать одновременно. Я использую Retrofit для связи с этими apis и использования GSON для сериализации/десериализации.

Что я делал раньше

Я создал два Retrofit RestAdapters и использовал шаблон Locator для получения их при необходимости. Адаптер RestAdapter, предназначенный для моего собственного api, включает в себя GSONConverter с некоторыми пользовательскими TypeAdapters, так как я не хочу 1:1 десериализации JSON моего ответа в приложении. Другой RestAdapter предназначен для стороннего api и использует другой GSONConverter с определенной политикой именования полей.

Проблема

Я пытаюсь использовать DI вместо Service Locator для получения моего RestAdapter (и интерфейса API). У меня есть настройка класса NetModule, как показано ниже.

@Module
public class NetModule {

    private static final String MY_API_URL = "my_api_url";
    private static final String THIRD_PARTY_API_URL = "third_party_api_url";

    @Provides
    @Singleton
    Cache provideOkHttpCache(Application application) {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        return new Cache(application.getCacheDir(), cacheSize);
    }

    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(Cache cache) {
        OkHttpClient client = new OkHttpClient();
        client.setCache(cache);
        return client;
    }

    @Provides
    @Singleton
    TypeAdapter<MyClass> provideMyAPITypeAdapter() {
        return new TypeAdapter<MyClass>() {
            // implementation ignored
        };
    }

    @Provides
    @Named("myApiGson")
    Gson provideGsonForMyAPI(TypeAdapter<MyClass> adapter) {
        return new GsonBuilder()
                .registerTypeAdapter(MyClass.class, adapter)
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();
    }

    @Provides
    @Named("thirdPartyApiGson")
    Gson provideGsonForThirdPartyAPI() {
        return new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .create();
    }

    @Provides
    @Named("myApiRestAdapter")
    RestAdapter provideMyRestAdapter(Gson gson, OkHttpClient okHttpClient) {
       return new RestAdapter.Builder()
                .setEndpoint(MY_API_URL)
                .setConverter(new GsonConverter(gson))
                .setClient(new OkClient(okHttpClient))
                .build();
    }

    @Provides
    @Named("thirdPartyApiRestAdapter")
    RestAdapter provideThirdPartyRestAdapter(Gson gson, OkHttpClient okHttpClient) {
       return new RestAdapter.Builder()
                .setEndpoint(THIRD_PARTY_API_URL)
                .setConverter(new GsonConverter(gson))
                .setClient(new OkClient(okHttpClient))
                .build();
    }

    @Provides
    @Singleton
    MyAPI provideMyAPI(RestAdapter adapter){
        return adapter.create(MyAPI.class);
    }

    @Provides
    @Singleton
    ThirdPartyAPI provideThirdPartyAPI(RestAdapter adapter){
        return adapter.create(ThirdPartyAPI.class);
    }
}

Как вы можете видеть выше в коде, NetModule имеет методы для возврата двух объектов Gson и двух объектов RestAdapter. Мои вопросы:

  • Как я могу убедиться, что правильные зависимости вводятся при создании определенных интерфейсов RestAdapter и API? (provideMyRestAdapter() требуется, чтобы GSON возвращалась из provideGsonForMyAPI(), а provideMyAPI() требовала, чтобы RestAdapter возвращался из provideMyRestAdapter().)

  • Как я могу убедиться, что только два экземпляра RestAdapter (один для моего api и другого для сторонних api) когда-либо создаются во время жизни приложения, поскольку создание RestAdapter считается дорогостоящим. Я использую атрибут @Named для методов, возвращающих RestAdapters. Скажем, например, при прямом вводе зависимости к полю: @Inject("myApiRestAdapter") RestAdapter myRestadapter; - Dagger 2 собирается создавать новый RestAdapter каждый раз или он будет использовать ранее созданный (например, @Singleton, но для определенного объекта)?

Я только что начал использовать Dagger 2, и мое понимание того, как его использовать, может быть неверным. Пожалуйста, поправьте меня, если я что-то делаю неправильно. Спасибо, что поднял этот длинный вопрос.

4b9b3361

Ответ 1

Вы уже на полпути через решение. Чтобы завершить решение, попробуйте сделать следующее:

@Provides
@Named("myApiRestAdapter")
RestAdapter provideMyRestAdapter(@Named("myApiGson") Gson gson, OkHttpClient okHttpClient) {
   return new RestAdapter.Builder()
            .setEndpoint(MY_API_URL)
            .setConverter(new GsonConverter(gson))
            .setClient(new OkClient(okHttpClient))
            .build();
}

@Provides
@Named("thirdPartyApiRestAdapter")
RestAdapter provideThirdPartyRestAdapter(@Named("thirdPartyApiGson") Gson gson, OkHttpClient okHttpClient) {
   return new RestAdapter.Builder()
            .setEndpoint(THIRD_PARTY_API_URL)
            .setConverter(new GsonConverter(gson))
            .setClient(new OkClient(okHttpClient))
            .build();
}

Чтобы убедиться, что в течение всего срока службы приложения создаются только два экземпляра ваших резервных копий, аннотируйте оба метода, предоставляющие RestAdapter с @Singleton, как это было сделано другими способами. Что касается вашего другого вопроса, будет ли Dagger 2 создавать новый экземпляр RestAdapter каждый раз, когда он должен его вводить, я думаю, что он делает это точно, но я не уверен в этом.

Надеюсь, это поможет!