2017-06-12 55 views
0

鑑於下面的例子:是否可以避免父類中的不必要注入?

class CustomView extends View { 
    @Inject 
    SomeObject mObject; 

    @Override 
    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     getApplicationComponent().inject(this); 
    } 
} 

class SecondaryCustomView extends CustomView { 
    @Inject 
    AnotherObject mAnotherObject; 

    @Override 
    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     getApplicationComponent().inject(this); 
    } 
} 

兩個自定義視圖可以在佈局被獨立地使用。第二個只比第一個更專業。如你所見,兩個都有注入的字段,都需要調用inject()。問題是,當SecondaryCustomView調用其inject()時,Dagger注入AnotherObject的實例和SomeObject的實例。在調用super.onFinishInflate()之後,它創建了SomeObject的第二個實例。這本身不是問題,但我們至少會創造不必要的對象。

有沒有辦法避免這種情況?有一種方式告訴Dagger注入了一個子類,那麼忽略父注入?

舉例來說,組件看起來是這樣的:

@Component(...) 
public interface AppComponent { 
    void inject(CustomView); 
    void inject(SecondaryCustomView); 
} 
+0

你還可以發佈你的組件的接口嗎? – azizbekian

+0

這只是一個例子。如果您想知道注入對象的範圍,請考慮爲每次注入創建一個新實例。 – fhsilva

+0

我感興趣接口方法簽名中'this'的類型是什麼。 – azizbekian

回答

0

有沒有辦法在匕首要做到這一點,但你可以自己做。

要同意並在評論中擴大你的觀點:

是的,它是需要的。如果我們僅在父代使用注入,Dagger不會注入子對象。但是,如果從子項調用父對象,它會注入父對象。

這是正確的,並在"A note about covariance"指出:雖然inject(Foo)可以接受富或任何其子類的實例,匕首的一個編譯時框架;將不會生成inject(Foo)來注入屬於Foo任意子類的字段,因爲在編譯時這是不可能知道的。這可能有點令人驚訝,特別是如果你的組件同時具有inject(Foo)inject(FooSubclass),就像你在CustomView和SecondaryCustomView中所看到的一樣:名稱爲injectCustomViewinjectSecondaryCustomView顯然只有前者可以從Foo中調用。

從簡單地設置一個 injectedAlready布爾字段作爲標誌

除此之外,一個方法是建立一個可覆蓋的方法,該方法不調用其超類的實現:如果你正在尋找一個類似的解決方案

class CustomView extends View { 
    @Inject 
    SomeObject mObject; 

    @Override 
    protected void onFinishInflate() { 
     injectMe(); 
     super.onFinishInflate(); 
    } 

    protected void injectMe() { 
     getApplicationComponent().inject(this); // inject(CustomView); 
    } 
} 

class SecondaryCustomView extends CustomView { 
    @Inject 
    AnotherObject mAnotherObject; 

    @Override 
    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     // ... 
    } 

    /** Despite looking identical, the JVM can call the more-specific overload here. */ 
    @Override protected void injectMe() { 
     getApplicationComponent().inject(this); // inject(SecondaryCustomView) 
    } 
} 

活動和片段類,您可以使用dagger.android;那裏的內置機制使用類的運行時類型從Map動態獲取正確的AndroidInjector。但是,該解決方案目前不支持View,因此這與您爲特定情況獲得的結果差不多。

+0

不錯的解決方案!謝謝! – fhsilva