Dagger.android UserScope

时间:2018-03-02 15:22:39

标签: android dagger

我正在尝试使用https://google.github.io/dagger/android创建UserScope我有@Singleton@ActivityScope@FragmentScope@UserScope

AppComponent

@Singleton
@Component(
  modules = [
    AndroidSupportInjectionModule::class,
    ActivityBindingModule::class,
    AppModule::class,
    ApiModule::class
  ]
)
interface AppComponent {

  fun inject(application: Application)

  fun createUserComponent(): UserComponent.Builder

  @Component.Builder
  interface Builder {

    @BindsInstance
    fun application(app: Application): Builder

    fun apiModule(module: ApiModule): Builder

    fun build(): AppComponent
  }
}

UserComponent:

@UserScope
@Subcomponent(
  modules = [UserModule::class]
)
interface UserComponent {

  @Subcomponent.Builder
  interface Builder {
    @BindsInstance
    fun user(user: User): Builder

    fun build(): UserComponent
  }
}

UserModule:

@Module
class UserModule {

  @UserScope
  @Provides
  fun provideUser(user: User): User = user
}

以下是我在成功登录后创建UserComponent的方式:

 private fun createSession(user: User) {    
      userComponent = appComponent.createUserComponent().user(user).build()
  }

我还有UserManager,它引发User注入构造函数参数的问题

@UserScope
class SomeManager @Inject constructor(
    private val apiService: ApiService,
    private val user: User
) {}
  

错误讯息:错误:[dagger.android.AndroidInjector.inject(T)]   如果没有@Inject,则无法提供domain.model.authorize.User   构造函数或来自@ Provide-annotated方法。

     

di.modules.MainActivityBindingModule_ContributeUserFragment.UserFragmentSubcomponent   使用@ di.scopes.FragmentScope作用域可能不会引用绑定   不同的范围:@ di.scopes.UserScope类   domain.managers.SomeManager

我想创建@UserScope来管理相关的ApiManagers生命周期

UPD

@Module
class UserFragmentModule {

  @Provides
  @FragmentScope
  fun provideViewModelFactory(someModule: SomeModule) = UserFragmentViewModelFactory(someModule)
}

ContributesAndroidInjector逻辑:

@Module
interface ActivityBindingModule {

  @ActivityScope
  @ContributesAndroidInjector(modules = [SplashModule::class])
  fun contributeSplashActivity(): SplashActivity

  @ActivityScope
  @ContributesAndroidInjector(modules = [SignInModule::class])
  fun contributeAuthorizeActivity(): Activity

  @ActivityScope
  @ContributesAndroidInjector(modules = [MainModule::class])
  fun contributeMainActivity(): MainActivity
}


@Module(includes = [MainActivityBindingModule::class])
class MainModule


@Module
interface MainActivityBindingModule {

  @FragmentScope
  @ContributesAndroidInjector(modules = [UserFragmentModule::class])
  fun contributeUserFragment(): UserFragment
}

2 个答案:

答案 0 :(得分:0)

您正在尝试注入仅在User中的@UserScope中提供的@FragmentScope实例。

基本上,规则是每当您需要User注入时 - 您需要加入@UserScope

您需要在所有地方更改@FragmentScope@UserScope注释。

根据您发布的内容,我相信它就在这里:

@Module
class UserFragmentModule {

  @Provides
  @UserScope
  fun provideViewModelFactory(someModule: SomeModule) = UserFragmentViewModelFactory(someModule)
}

您需要将UserFragmentModule移至UserComponent

@UserScope
@Subcomponent(
  modules = [UserModule::class, UserFragmentModule::class]
)
interface UserComponent {

而且您还需要将application.userComponent注入UserFragment

这是一个很好的article about subcomponents。我建议你阅读它以获得充分的理解。

另一种选择,我不确定这个,但也许你可以用你的application.userComponent注入你的UserFragment。

答案 1 :(得分:0)

我认为您的问题是使用范围错误。 范围帮助我们处理注入的项目生命周期,以防止在整个应用程序生命周期中保持不需要的对象。

enter image description here

并查看此图片:

enter image description here

您的模块应与组件的范围相同。 例如,在AppComponent中,ActivityBindingModuleActivityScope。你为什么这样做?

我认为最好让activityComopnent依赖appComponent。如果您的activityComponent在上限范围组件(appComponent)中具有某些依赖关系,则首先添加该组件的依赖关系。 (dependencies= [ AppComponent::class])。其次,您必须使用返回所需依赖项对象的方法在appComponent中公开所需的依赖项。最后在wireUpping中,你应该在Dagger wire upping中调用appComponent作为调用活动模块。 (我将在一个例子中显示这个) 所以你需要的就是这样的activityComponent:

@ActivityScope
@Component(modules = [ActivityBindingModule::class],dependencies= [ AppComponent::class])
interface activityComponent {
.
.
.

这是我用java编写的示例,它显示了如何连接 appComponent activityComponent

@Singleton
@Component(modules = {ApplicationModule.class ,ServicesModule.class})
public interface ApplicationComponent {

void inject(ImicoApplication imicoApplication);

// exposed for child-components.
Context getContext();
Application getApplication();
CompanyService getCompanyService();
CategoryService getCategoryService();
RatingService getRatingService();
NewsService getNewsService();
AuthorizationManager getAuthorizationManager();
}

这是 activityComponent

@ActivityScope
@Component(dependencies = {ApplicationComponent.class},modules = {SearchActivityModule.class})
public interface SearchserviceComponent {

    void inject (SearchFragment searchFragment);
}

在SearchFragment中执行此操作以进行连线:

DaggerSearchserviceComponent.builder()
        .applicationComponent(((ImicoApplication) getActivity().getApplication()).getApplicationComponent())
        .searchActivityModule(new SearchActivityModule(this)).build().inject(this);

如果在SearchFragment中我需要 CompanyService ,只需注入它,它就会被applicationComponent提供并公开。