android - 在 Android 上使用 Dagger 2 进行延迟注入(inject)

标签 android dependency-injection lazy-initialization dagger-2

我是 Dagger 2 的新手。我有这种情况,我不想在我的应用程序中注入(inject)对象(在演示者中,在 api 中)

我最初没有办法提供它。它是在我的应用程序的某个阶段进行身份验证后才创建的。

来自文档 http://google.github.io/dagger/

我看到延迟加载可能是解决这个问题的一种方法,例如

@Inject 
Lazy<Grinder> lazyGrinder;

然后使用以下方法获取这样的值: lazyGrinder.get().grind();

我的问题是:

  • 在此之后我可以安全地将对象换成新对象吗?
  • 还有其他推荐的方法吗?

谢谢

最佳答案

这不适合 Lazy . Lazy是延迟昂贵的对象初始化的好方法,但它暗示了一些您不想要或不需要的语义,特别是关于您想要的“安全交换”行为。

简单来说,Lazy 是一个 Provider wrapper memoizes本地:

  • 如果您从不调用 get , Dagger 永远不会创建有问题的对象。
  • 第一次调用 get创建并存储对象实例。
  • 第二次调用get返回相同的实例,以此类推,无论对象是否被标记为 Singleton。

这使得 Lazy 成为昂贵对象的绝佳选择,否则它会是一个字段(但可能永远不会被使用)。然而,如果引用可能会改变(如你所愿),Lazy 只会让人感到困惑:它会在第一次使用时存储值并且从不在本地更新,因此无论怎样,多个过时的副本可能会在你的应用程序中 float 任何给定时间的“正确”值。


从您的示例中借用 Grinder 的使用,更好的解决方案包括:

  • 使用 @Provides方法返回模块中的字段,稍后可以更新。您需要注入(inject) Provider<Grinder>对于每个长期存在的对象实例,因为仅注入(inject)对 Grinder 的引用不会更新。如果您有很多短暂的对象,这仍然可能是最好的选择。

    引用是隐式的单例,但没有这样注释,因为你自己控制实例。 Dagger 会调用你的 getGrinder方法频繁。

    @Module public class YourModule {
      private Grinder grinder;
    
      public void setGrinder(Grinder grinder) {
        this.grinder = grinder;
      }
    
      @Provides public Grinder getGrinder() {
        return grinder;
      }
    }
    
    /* elsewhere */
    YourModule module = new YourModule();
    YourComponent component = DaggerYourComponent.builder()
        .yourModule(module)
        .build();
    /* ... */
    module.setGrinder(latestAndGreatestGrinder);
    
  • 正如 EpicPandaForce 在评论中提到的,创建/绑定(bind)提供当前实例并允许更新的单例 GrinderHolder、GrinderController 或 AtomicReference 对象。这样就不可能直接注入(inject) Grinder,但注入(inject)获取当前正确 Grinder 的对象却很容易且显而易见。如果您的单例 GrinderHolder 实现直到您第一次请求时才创建 Grinder,那么您实际上已经自己创建了一个 Lazy 单例。

关于android - 在 Android 上使用 Dagger 2 进行延迟注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34049807/

相关文章:

java - Guice 多重绑定(bind)实例获得不同的依赖实例

java - 我们可以在另一个类中传递注入(inject)的对象吗

java - 为什么我不能像这样在 Java 中延迟初始化静态长数组?

oop - 为什么我们同步懒惰的单例而不同步急切的单例?

android - 从 SharedPreferences 读取与保留对象实例

android - Appcelerator Android 服务后台停止

c# - 依赖注入(inject)和内部辅助类

swift 2.0 : infer closure type error

java - 多路开关中开关盒的解决方案

java - 安卓/Java : convert UTF-8 to UTF-16