2017-06-12 53 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