2015-12-02 59 views
10

我是新来的匕首2.我有这样的情况,我wan't注入在我的应用程序的对象(在演讲中,API)懒注射用匕首2在Android

我没有最初提供的方式。它不会在我的应用程序的某个阶段进行身份验证之后才创建。

从文档http://google.github.io/dagger/

我看延迟加载可能是解决这个如

@Inject 
Lazy<Grinder> lazyGrinder; 

,然后获得价值像这样的方式利用: lazyGrinder.get()磨() ;

我的问题是:

  • 我可以安全地交换对象后,这与一个新的?
  • 有没有其他推荐的方法来做到这一点?

感谢

+0

你是什么意思的重写? – cyroxis

+0

@cyroxis我的意思是交换,问题已更新 – AndroidEnthusiast

+0

我只用过'懒惰'一次。它让我在创业时陷入僵局。再也不。顺便说一句,我不知道我做错了什么。我个人会创建一个单独的'Holder'对象,就像在'GrinderHolder'中一样,并且在你有它的时候设置它(否则为'null') – EpicPandaForce

回答

19

这不是Lazy一个很好的匹配。 Lazy是延迟昂贵的对象初始化的好方法,但它隐含了一些您不想要或不需要的语义,特别是关于您想要的“安全交换”行为。

简单地说,懒惰是一个供应商的包装,memoizes本地:

  • 如果你从来没有叫get,匕首从不制造问题的对象。
  • 第一次调用get创建并存储对象实例。
  • 第二次调用get会返回相同的实例,永远是这样,无论对象是否标记为Singleton。

这使Lazy成为昂贵的对象的一个​​很好的选择,否则它可能是一个字段(但可能永远不会使用)。但是,如果引用可能会改变(如您的意愿),Lazy会简单地造成混淆:它将在第一次使用时存储该值并且从不在本地更新,因此多个过期副本可能会在应用程序中浮动的“正确”价值在任何给定的时间。


要从例如借使用磨床,更好的解决方案包括:

  • 使用@Provides方法,在一个模块,它可以以后更新返回现场。您需要为每个长寿命对象实例注入Provider<Grinder>,因为单独向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评价所提到的,创建/结合一个单GrinderHolder,GrinderController,或的AtomicReference对象,它提供当前实例并允许更新。这样就不可能直接注入研磨机,但是注入获取当前正确研磨机的物体很容易且明显。如果你的单件GrinderHolder实现在你第一次请求它时才创建Grinder,那么你已经有效地创建了一个懒惰单例。

4

如果在组件创建时无法提供对象,请不要将它添加到组件图中!这是要求混淆图形依赖性和不一致性。您正在考虑的更好的解决方案是@Subcomponent方法,该方法允许您创建一个从父级继承依赖关系的新组件,但也会添加一个新组件。下面是一个例子:

@Component 
interface RegularComponent { 
    @AppInstanceId String appInstanceId(); // unique per app install; not related to logging in 
    AuthenticatedComponent newAuthenticatedComponent(); 
} 

@Subcomponent 
interface AuthenticatedComponent { 
    Set<Friend> friends(); 
    @AccountId String accountId(); 
} 

在此,在子组件可以使用appInstanceId提供帐户ID的@AccountId(如果需要),因为与它的父组件的子组件股依赖性。

如果您需要为子组件提供状态(包括accountId,auth令牌等),请将其作为参数传递给@Module,并将其存储在private final字段中。您可以阅读关于如何提供子组件模块in the documentation的更多信息。