匕首2-目标方法提供的对象需要实例

时间:2019-03-21 08:44:56

标签: java dagger-2 json-deserialization dagger

我需要在匕首2中为TimeStamp的{​​{1}}的{​​{1}}方法提供deserialize

JsonDeserializer

但是该对象需要@Singleton @Provides public JsonDeserializer provideJsonDeserializer() { return new JsonDeserializer() { public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Timestamp(json.getAsJsonPrimitive().getAsLong()); } }; } 中的JsonElement个对象。如何将那个对象传递给我的JsonDeserializer方法。

provideTimestamp

或者我不应该通过匕首注入@Singleton @Provides public Timestamp provideTimestamp() { } ,如果是这样的话,有人可以解释原因,那可能有助于我更多地了解匕首2。

1 个答案:

答案 0 :(得分:0)

您在第一个代码示例中拥有它的方式是正确的,以及我的使用方式:您应该调用new Timestamp(...),而不是使用Dagger。

您应该绘制的区别是可注入对象与可更新对象:应注入图形中的哪些对象,以及应使用new创建哪些对象?可能很容易想到,每次对new的调用都是不好的,因为它降低了灵活性,但现实是,它更多地是一种判断调用:

  • 如果您想更改或替换实现,即使通过在测试中使用测试双精度或模拟,您的对象也应该是 injectable 。对于不确定性或昂贵的对象尤其如此,因为您可能希望测试快速且确定性。
  • 如果实现是“值对象”,其作用不只是携带结构化数据,则它们不太可能被替换,并且可能是可更新的
  • 如果实现的依赖性很小并且易于创建,则它们可能是可更新的。如果实现将大量服务用作构造函数参数(而不是许多数据值),则它们可能应该是 injectable ;这将是在测试中使用伪造品或模拟品的好理由。

另请参见: To “new” or not to “new”…,作者:MiškoHevery


如上所述,Timestamp是一个值对象:您不太可能想替换实现,Timestamp除了每个实例数据外没有其他依赖项,并且实现非常容易创建。这使Timestamp成为 newable 的极佳候选者。

在您的情况下,您还有其他问题:新时间戳将根据您传入的json对象而变化,而json对象将变化得足够大,以至于您想将其放在Dagger图形中。这意味着如果您 did 想要进行注入而不是注入时间戳,则可能需要注入TimestampFactory,它可以是constructor referenceAutoFactory-创建的实现或任何其他实现:

interface TimestampFactory {
  Timestamp create(long value);
}

这似乎有些过分,但是让我们假装,您想要的是Timestamp2,它​​还记录了一天中的当前时间,因此可能会使测试变得困难。在这种情况下,您可以注入时间戳工厂

@Singleton
@Provides
public JsonDeserializer provideJsonDeserializer(Timestamp2Factory tsFactory) {
  return new JsonDeserializer() {
    public Timestamp2 deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context) throws JsonParseException {
      return tsFactory.create(json.getAsJsonPrimitive().getAsLong());
    }
  };
}

@Reusable
@Provides
public Timestamp2Factory provideTimestamp2Factory() {
  // Merge in other parameters and dependencies if needed,
  // but Timestamp2 only needs one value that create(long) supplies.
  return Timestamp2::new;
  // or, pre-Java-8:
  return new Timestamp2Factory() {
    @Override public Timestamp2 create(long time) {
      return new Timestamp2(time);
    }
  }
}

这将允许您在测试中调用provideJsonDeserializer并传递您选择的TimestampFactory,例如使用伪造的系统时间而不是真实的系统时间的TimestampFactory。这样可以使您的测试更加安全和更具确定性。

但是,由于您想要的是快速,确定性值对象Timestamp,它没有RPC服务,文件系统访问或实际系统时间之类的外部依赖性,因此请按照您的问题继续进行new Timestamp调用。