【问题标题】:Runtime swap implementation for Dagger provided dependency [duplicate]Dagger 提供的依赖项的运行时交换实现 [重复]
【发布时间】:2017-03-16 20:30:42
【问题描述】:

使用 Dagger 2,我有一个提供给演示者的域对象。该域对象依赖于存储库。该存储库有两个实现,但都实现了相同的接口。我需要能够以某种方式设置 dagger,以便在运行时根据用户选择“演示模式”选项在存储库的两个实现之间进行交换。

所以我有以下域对象:

public class SomeAwesomeBusinessLogic {

    Repository repository;

    @Inject
    public SomeAwesomeBusinessLogic(Repository repository) {
        this.repository = repository;
    }
    //awesome stuff goin down
}

还有两个仓库:

public RemoteRepository implements Repository {

    @Inject
    public RemoteRepository() {
        //setup
    }
}

public DemoRepository implements Repository {

    @Inject
    public DemoRepository() {
        //setup
    }
}

关于如何构建我的模块和组件以使其工作的任何想法?

【问题讨论】:

    标签: dagger-2


    【解决方案1】:

    我想到了几个想法。取决于您想要交换的方式和时间。一种可能性是使用配置实例化您的模块。可以是一个简单的布尔值:

    @Module
    public class RepositoryModule {
      private final boolean isDemo;
    
      public RepositoryModule(boolean isDemo) {
        this.isDemo = isDemo;
      }
    
      @Provides
      public Repository providesRepository() {
        return isDemo? new DemoRepository() : new RemoteRepository();
      }
      // Other providers
    }
    

    我不喜欢这种方法,但它适合您的用例。我相信这是相当严格的,并且不允许易于维护。我可能会选择使用工厂并提供工厂而不是仓库本身。

    public interface RepositoryFactory {
       Repository getRepository(Configuration configuration);
    }
    
    public class RepositoryFactoryImpl implements RepositoryFactory {
    
       @Inject
       public RepositoryFactoryImpl() {}
    
       // The implementation
    }
    
    @Module
    public class RepositoryModule {
      @Provides
      public RepositoryFactory providesRepositoryFactory(
                RepositoryFactoryImpl factory) {
        return factory;
      }
      // Other providers
    }
    

    Configuration 将是一个简单的 POJO,您可以在其中指定多个属性来配置您的存储库。比如说:

    public class Configuration {
       private final boolean isDemo;
       // all the POJO stuff you need
    }
    

    然后您可以使您的域对象依赖于工厂:

    public class SomeAwesomeBusinessLogic {
    
       private final RepositoryFactory repositoryFactory;
    
       @Inject
       public SomeAwesomeBusinessLogic(
                    RepositoryFactory repositoryFactory) {
          this.repositoryFactory = repositoryFactory;
       }
       //awesome stuff going down
    }
    

    然后您可以在业务逻辑中执行repositoryFactory.getRepository(new Configuration(true/false));。

    我更喜欢这种方法,因为它更容易扩展到新类型的存储库。您还可以测试工厂逻辑是否正确。通常没有人测试 dagger 模块,这就是为什么我不太热衷于第一种方法。

    另一个好处是,如果有可能更改应用程序的配置并突然更改为演示存储库,这种方法允许您保留相同的模块实例,方法是向工厂提供不同的 Configuration 对象。

    第三种可能是Producers。但是,这实际上取决于您的用例以及您希望如何处理此运行时依赖项交换。我觉得这种方法很好,但可能有点矫枉过正。

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多