Кинжал, как внедрить одну реализацию в код - PullRequest
0 голосов
/ 08 апреля 2020

Я Android разработчик и новичок в чистой архитектуре.

У меня есть класс usecase1, который внедряется с экземпляром Repository через внедрение конструктора:

 public class usecase1 {

    public final Repository repository;
    @Inject
    public usecase1(Repository repository) {
        this.repository = repository;
    }

    List<String> getlist(){
        return repository.list();
    }
}

на уровне базы данных у меня есть 2 реализации. один для локальных и один для целых rnet извлечения данных.

в кинжале Я создаю 2 метода с аннотацией @named для онлайн и офлайн и возвращаю реализацию. это код модуля:

 @Provides
@Singleton
@Named("Online")
Repository getRepository(){
  return new OnlineRepository();
}

@Provides
@Singleton
@Named("Offline")
Repository getRepository(){
    return new OfflineRepository();
}

@Provides
@Singleton
@Named("Offline")
Usecase1 getusecase1offline(@Named("Offline")Repository repository){
    return new usecase1(repository);
}

@Provides
@Singleton
@Named("Online")
Usecase1 getusecase1online(@Named("Online")Repository repository){
    return new usecase1(repository);

Моя проблема в том, как ввести соответствующую зависимость. и как сказать кинжалу, который вводит автономный или сетевой вариант использования.

1 Ответ

1 голос
/ 08 апреля 2020

Не видя других битов, о которых я спрашивал, я могу только дать столько советов, которые не равносильны догадкам. Другими словами, помогите мне помочь вам.

в Module, который предоставляет usecase1 экземпляров, вы можете сделать что-то вроде этого:

@Module
class MyModule {
  // if you're provided qualified references for the usercase1 class
  // itself, then you could provide two implementations that use the same
  // qualifier as the Repository types they depend on (or choose another 

  @Provides @Named("Online")
  Repository provideOnlineUsecase1(@Named("Online") repository) {
    return new usecase1(repository);
  }

  @Provides @Named("Offline")
  Repository provideOfflineUsecase1(@Named("Offline") repository) {
    return new usecase1(repository);
  }

  // ...alternatively, if you're not providing qualified references of
  // usecase1 you can simply pick one. this might be the case if you're 
  // doing some manual testing and don't mind periodically rebuilding the
  // project switching between "Online" and "Offline":

  @Provides 
  Repository provideUsecase1(@Named("Offline") repository) {
    return new usecase1(repository);
  }
}

Ключевой момент является то, что ваши квалифицированные Repository экземпляры связаны, ссылаясь на них в методе поставщика-поставщика как параметры, аннотированные с таким же именованным квалификатором.

другими словами, так как OfflineRepostiory предоставляется с @Named (" Квалификатор Offline "), другой поставщик, которому он нужен, может обратиться к нему, объявив его как параметр типа Repository, помеченный @Named (" Offline ").

В качестве отступления ... в общем, кажется, что ваши типы (usecase1, Repository) имеют природу, которая обычно должна быть только одноэлементным экземпляром, но я не вижу никаких модификаторов области видимости в вашем фрагменте кода.

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

** Обновление **

Из вашего комментария кажется, что вам интересно, как переключаться между двумя различными Repository реализациями, основанными на динамически вычисляемое значение (например, состояние сетевого подключения). В этом случае я, вероятно, сделал бы что-то вроде этого:

@Module
class MyModule {
  @Provides @Named("Online") 
  Repository provideOnlineRepository() {...}

  @Provides @Named("Offline") 
  Repository provideOfflineRepository() {...}

  @Provides
  Supplier<Boolean> provideIsConnectedSupplier() {...}

  @Provides
  Repository provideUseCase(
    Supplier<Boolean> isConnectedSupplier,
    @Named("Online") Repository onlineRepository,
    @Named("Offline") Repository offlineRepository) {

      return new usecase1(
        isConnectedSupplier, 
        onelineRepository, 
        offlineRepository);
  }
}

В этой настройке usecase1 предоставляется объект, который он может запросить, чтобы узнать, есть ли у него сетевое соединение, а затем использовать Repository, что соответствует результату. это дает преимущество в том, что вы можете разрабатывать и тестировать все свои компоненты независимо, и вы используете Dagger просто для того, чтобы собрать их все (вместо того, чтобы помещать переключающие логи c в свой модуль).

с точки зрения дизайна Вы можете сделать это намного лучше (например, используя потоки), но, надеюсь, этого достаточно, чтобы вдохновить некоторые идеи.

...