【问题标题】:Dagger how to inject one implementation in codeDagger 如何在代码中注入一种实现
【发布时间】:2020-04-08 03:35:45
【问题描述】:

我是一名 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 个实现。一种用于本地数据,另一种用于互联网获取数据。

在匕首中,我为在线和离线创建了 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);

我的问题是如何注入适当的依赖。以及如何说 dagger 注入离线或在线用例。

【问题讨论】:

  • 你能分享你的模块和组件代码吗?
  • @homerman 我认为这些课程并不重要。在我的 viewmodel 构造函数中,我注入了存储库。我怎么说匕首要离线或在线注入哪个存储库。

标签: android dagger-2


【解决方案1】:

没有看到我询问的其他内容,我只能提供很多不等于猜测的建议。换句话说,帮我帮你。

在提供usecase1 实例的Module 中,您可以执行以下操作:

@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("离线”)。

顺便说一句...从广义上讲,您的类型(usecase1Repository)似乎具有通常只需要单例实例的性质,但我在您的代码sn-p。

请记住,多分享一些关于您的问题的信息可能会产生更好的反馈。希望对您有所帮助。

** 更新**

从您的评论看来,您似乎想知道如何根据动态计算的值(如网络连接状态)在两个不同的 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 只是为了组装它们(而不是将切换逻辑放入您的模块中)。

从设计的角度来看,您可以做得比这更好(例如使用流),但希望这足以激发一些想法。

【讨论】:

  • 对不起,我编辑我的答案。我的意思是在视图模型中我注入用例如何注入适当的实例。我有一个条件是连接状态。我可以在模块中使用连接状态。也许我可以使用制造工厂。并返回适当的用例
  • 好的,我想我明白了。请参阅我的答案的更新。如果您说的不是这个,请告诉我。
  • 非常感谢,当然,我想到了。但问题是我们将两个存储库实例传递给不好的域层,也许明天我们有 3 或 4 个存储库。我使用 rxjava 来实现这个场景,还不错。但它并不适合我
  • 我可能会将基于连接的切换逻辑推送到单个 Repository 中,作为 OnlineRepositoryOfflineRepository 的外观,或者只是将这两个合并为单个 @987654336 @ 根据连接状态进行自我管理。这样您的用例就不必考虑连接状态(就您而言)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 2023-03-20
  • 2020-05-22
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多