[英]Understanding Dagger2 subcomponents
我的应用程序中包含以下Dagger2体系结构:
-- AppComponent (@PerApplication)
-- UserComponent (@PerUser)
-- ActivityComponent (@PerActivity)
-- ChatComponent (@PerActivity) <-- 1
其中:AppComponent:
@PerApplication
@Component(modules = {ApplicationModule.class, StorageModule.class, NetworkModule.class})
public interface ApplicationComponent {
UserComponent plus(UserModule userComponent);
//Exposed to sub-graphs.
Context application();
}
UserComponent:
@PerUser
@Subcomponent(modules = {UserModule.class, RosterModule.class})
public interface UserComponent {
ActivityComponent plus(ActivityModule activityModule);
User getMe();
UserRepository userRepository();
}
ActivityComponent:
@PerActivity
@Subcomponent(modules = ActivityModule.class)
public interface ActivityComponent {
ChatComponent plus(ChatModule chatComponent);
//Exposed to sub-graphs.
Context context();
}
ChatComponent:
@PerActivity
@Subcomponent(modules = {ChatModule.class})
public interface ChatComponent {
void inject(ChatListFragment chatListFragment);
void inject(ConversationFragment conversationFragment);
void inject(NewConversationFragment newConversationFragment);
void inject(CloudFilesFragment cloudFilesFragment);
void inject(ChatActivity chatActivity);
void inject(ConversationActivity conversationActivity);
void inject(NewConversationActivity newConversationActivity);
void inject(NewGroupActivity newGroupActivity);
void inject(NewGroupFragment newGroupFragment);
}
我面临2个问题:
首先,如何为课程注入不同的Context
? 应用程序或活动?
其次,在尝试编译我的代码时,我面临一个奇怪的问题,错误是:
错误:(23,10)错误:如果没有@Provides注释的方法,则无法提供br.com.animaeducacao.ulife.domain.interactor.UseCase。 br.com.animaeducacao.ulife.presentation.view.fragment.ChatListFragment.chatListPresenter [类型的插入字段:br.com.animaeducacao.ulife.presentation.presenter.ChatListPresenter chatListPresenter] br.com.animaeducacao.ulife.presentation.presenter ChatListPresenter。(br.com.animaeducacao.ulife.domain.interactor.UseCase chatDialogsUseCase,br.com.animaeducacao.ulife.domain.interactor.UseCase advisorUserPresence,android.content.Context context)[参数:@ javax.inject.Named( “ getChatDialogs”)br.com.animaeducacao.ulife.domain.interactor.UseCase chatDialogsUseCase]
我的ChatListFragment是:
@PerActivity
public class ChatListFragment extends BaseFragment implements ChatListView {
@Inject
ChatListPresenter chatListPresenter;
...
//called onActivityCreated()
private void initialize() {
this.getComponent(ChatComponent.class).inject(this);
}
BaseFragment:
protected <C> C getComponent(Class<C> componentType) {
return componentType.cast(((HasComponent<C>)getActivity()).getComponent());
}
ChatListPresenter:
@PerActivity
public class ChatListPresenter implements Presenter {
private final UseCase chatDialogsUseCase;
private final UseCase adviceUserPresence;
private final Context context;
private ChatListView chatListView;
@Inject
public ChatListPresenter(@Named("getChatDialogs") UseCase chatDialogsUseCase,
@Named("adviceUserPresence") UseCase adviceUserPresence,
Context context) {
this.chatDialogsUseCase = chatDialogsUseCase;
this.adviceUserPresence = adviceUserPresence;
this.context = context;
}
问题是,在我的ChatModule类中,我实现了所有必需的@Provides
:
@Provides
@PerActivity
@Named("getChatDialogs")
public UseCase provideChatDialogs(@Named("transactionalChatRepository") ChatRepository chatRepository, ThreadExecutor threadExecutor, PostExecutionThread postExecutionThread) {
return new GetUserChatDialogs(chatRepository, threadExecutor, postExecutionThread);
}
这是一个好方法吗? 为什么这里不编译,我在这里缺少什么? 对不起,很长的帖子,谢谢!
嗯,您有多个问题。
1)当你使用正确的subscoping到一个点(你正在 @Subcomponent
s请正确地在第一),该ChatComponent
实际上并不子范围其父组件-基本上, ChatComponent
不能@PerActivity
,它需要一个第四范围。
@Subcomponent
批注只是一种创建子范围内的组件的方法,而不必将其指定为组件依赖项。 它仍然需要自己的“更具体”的范围。
2.)为了使范围化工作有效,您需要在组件中为该组件要提供的每个依赖项指定配置方法,以便子范围内的组件可以继承它们。
例如,您的ApplicationComponent
没有提供StorageModule
内容的配置方法,因此StorageModule
提供的依赖项不能继承到子范围内的组件。
但是,我不确定如果不是在模块内部,是否可以仅指定要提供的类,而是使用@Inject
构造函数对其进行注释,并用范围标记该类。
而且,为了允许作用域层次结构A->B->C
中的C从A继承,那么B也需要具有A的提供方法。
因此, UserComponent extends ApplicationComponent
是必要的,而ActivityComponent extends UserComponent
,而ChatComponent extends ActivityComponent
。
3.)您应该使用@Named("application")
和@Named("activity")
批注指定两个不同的Context
,或者仅在模块中将它们称为Application
和Activity
,以免混淆起来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.