2017-03-22 65 views
2

我遇到类似this问题中的问题。 虽然接受的答案确实有帮助,但我错过了最后一块来解决问题。匕首 - 在不同组件上获取相同的实例

我有2个android库模块:commonexp这取决于common

common

一切:

@Module 
public class CommonModule { 
    @Singleton 
    @Provides 
    public Repository providesRepository() { 
     return new Repository(); 
    } 
} 

@Singleton 
@Component(modules={CommonModule.class}) 
public interface CommonComponent { 
    void inject(CommonClass commonClass); 
    /** 
     CommonClass needs instance of Repository 
    **/ 
} 

public class CommonDIHolder { 
    public static CommonComponent sComponent; 

    public static void init() { 
     sComponent = DaggerCommonComponent.builder().build(); 
    } 
} 

一切下exp

@Module(includes={CommonModule.class}) 
public class ExpModule { 
    @Singleton 
    @Provides 
    public ExpResource provideExpResource() { 
     return new ExpResource(); 
    } 
} 

@Singleton 
@Component(modules={ExpModule.class}, dependencies={CommonComponent.class}) 
public interface ExpComponent { 
    void inject(ExpClass expClass); 
    /** 
     ExpClass needs instance of Repository and ExpResource 
    **/ 
} 

public class ExpDIHolder { 
    public static ExpComponent sComponent; 

    public static void init() { 
     sComponent = DaggerExpComponent.builder() 
          .commonComponent(CommonDIHolder.sComponent) 
          .build(); 
    } 
} 

我同时需要CommonClassExpClass收到的Repository相同的实例。

此方法的问题是@Singleton不能取决于@Singleton。所以我必须将ExpComponent的范围改为自定义范围@ExpScope。然后我将provideExpResource更改为@ExpScope

然后我遇到一个错误,说ExpComponent可能不会引用与不同作用域的绑定。它指的是provideRepository,它有不同的范围(@Singleton)。如果我将范围更改为ExpScope,那么CommonComponentprovideRepository的范围将有所不同。

如果我改变了所有@Singleton@ExpScope然后我收到此错误信息:depends on scoped components in a non-hierarchical scope ordering

我该怎么办?或者我在这里做错了方法?

+0

的Android项目的良好的工作实例“因此,我必须将ExpComponent的范围改为自定义范围,称为** ExpScope **,然后将provideExpResource更改为** ExpScope **以及”Works正常用这个设置。使用匕首2.10。 – azizbekian

回答

1

使用一个且只有一个@Singleton范围的组件

你应该有一个且只有一个@Singleton范围的组件是这样的:

@Singleton 
@Component(modules={CommonModule.class, ExpModule.class}) 
public interface CommonComponent { 

} 

只有指定活动,片段和服务作为明确的注入组件目标

在Android应用程序中,您应该只列出A活动,碎片和服务作为注射点。你应该配置Dagger 2来注入其他依赖关系,而不必诉诸内部调用component.inject(this)

例如,如果你的CommonClass看起来是这样的:

public class CommonClass { 
    @Inject Repository repository; 

    public class CommonClass() { 
     CommonComponentHolder.get().inject(this); 
    } 
} 

重构这样的:

public class CommonClass { 
    private final Repository repository; 

    @Inject 
    public class CommonClass(Repository repository) { 
     this.repository = repository; 
    } 
} 

现在,当你有需要CommonClass,你与CommonComponent注入活动或片段或其子组件或从属组件之一,则它们可以获得CommonClass的实例,并且具有正确的依赖关系:

public class MyActivity extends AppCompatActivity { 

    @Inject CommonClass commonClass; 

    public void onCreate(Bundle savedInstanceState) { 
     CommonComponentHolder.getComponent().inject(this); 
    } 
} 

使用子或相关组件来指定目标注入

现在你有一个@Singleton范围的组成部分,你可能会想为您的活动或片段范围较窄创建一个组件。您必须将其连接到CommonComponent,因此使用相关组件或子组件(子组件比Dagger 2.10更受欢迎)。既然你说你已经试过定义一个@ExpScope,我认为缺少的一部分是使用注入活动或片段的@ExpScope来创建子组件或相关组件。

喜欢的东西的顶级单组分如下:

@Singleton 
@Component(modules={CommonModule.class, ExpModule.class}) 
public interface CommonComponent { 
    ExpComponent.Builder exComponent(); 
} 

然后为子:

@ExpScope 
@Subcomponent(modules = {NarrowerScopedModule.class}) 
public interface ExpComponent { 
    @Subcomponent.Builder 
    public interface Builder { 
     Builder narrowerScopedModule(NarrowerScopedModule narrowerScopedModule); 
     ExpComponent build(); 
    } 
} 

里有Google Android Architecture Blueprints Github repo

+0

'CommonComponent'不能引用'ExpModule',因为'exp'取决于'common',而不是相反。这是否意味着我必须在最顶层创建一个(这取决于'exp'和'common')哪个工作是构建组件的? –

+0

@AhmadFadli在单例级别创建一个组件。绑定应用程序范围(单例)依赖关系的所有模块。然后在活动级别创建不同的子组件,或者为活动或片段的范围使用模块 –

+0

好的,但是如何在每个活动中获取对子组件的引用?由于这些活动无法访问顶级组件。我正在考虑在每个android模块中创建一个单例类来存储已在顶层组件中构建的子组件。任何其他方式? –