2015-12-02 87 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的更多信息。