代码之家  ›  专栏  ›  技术社区  ›  Leandro Ocampo

匕首2:在一个物体中注入2个不同的范围

  •  0
  • Leandro Ocampo  · 技术社区  · 7 年前

    在有人开始将这个问题标记为重复之前,让我说我已经检查过这个 post ,但这并没有解决我的问题。

    正如标题所说,我需要在另一个对象中插入两个来自不同作用域的对象。 假设我们有下一种情况:

    我们有一个屏幕,让用户注册,然后,在同一个屏幕上,我们做一些基于用户会话的操作(例如:做一些同步)。

    对于我的项目,我计划使用子组件。到目前为止,我有下一个代码(简化)是基于这个 post :

    @Singleton
    @Component(modules = {AppModule.class})
    public interface AppComponent {
    
      static AppComponent init(MyApplication application) {
        return DaggerAppComponent.builder()
            .appModule(new AppModule(application))
            .build();
      }
    
      UserSessionComponent plusUserSessionComponent(UserSessionModule userSessionModule);
    
      void inject(MyApplication application);
    }
    
    @Module
    public class AppModule {
    
      private MyApplication myApplication;
    
      public AppModule(@NonNull MyApplication myApplication) {
        this.myApplication = myApplication;
      }
    
      @Provides
      @Singleton
      public AppSignUp provideAppSignUp() {
        return new AppSignUp();
      }
    }
    
    @UserSessionScope
    @Subcomponent(modules = {UserSessionModule.class})
    public interface UserSessionComponent {
    
      static UserSessionComponent init(AppComponent appComponent,
          UserSession userSession) {
        return appComponent.plusUserSessionComponent(userSession);
      }
    
      void inject(MyApplication myApplication);
    }
    
    @Module
    public class UserSessionModule {
    
      private UserSession userSession;
    
      public UserSessionModule(@NonNull UserSession userSession) {
        this.userSession = userSession;
      }
    
      @Provides
      @UserSessionScope
      public UserSessionSyncHelper provideUserSession(UserSession userSession) {
        return new UserSessionSyncHelper(userSession);
      }
    
    
      @Provides
      @UserSessionScope
      public UserSessionSync provideUserSession(UserSessionSyncHelper userSessionSyncHelper) {
        return new UserSessionSync(userSessionSyncHelper);
      }
    }
    

    现在,为了使它变得简单,假设我有一个组件(activity、viewmodel、presenter或其他什么组件),它将具有以下两个依赖项:

    public MyActivity extends AppCompatActivity {
    
      @Inject
      AppSignUp appSignUp;
    
      @Inject
      UserSessionSync userSessionSync;
    
      public void onCreate(Bundle savedInstanceState) {
        //to inject appSignUp
        MyApplication.getAppComponent().inject(this);
      }
    
      public onUserCreated(UserSession userSession) {
        //to inject userSessionSync
        MyApplication.getUserSessionComponent().inject(this);
      }
    }
    

    我这里的问题是dagger在第一次注入时会抱怨,因为appmodile没有usersessionsync。所以问题是,我怎样才能解决这个问题?匕首在这个场景中有什么特点吗?

    到目前为止,我只能在下一个解决方案中思考:

    使usersessionsync独立于dagger框架和内部

    public class UserSessionSync {
      @Inject
      UserSessionSyncHelper userSessionSyncHelper;
    
      public UserSessionSync(){
        MyApplication.getUserSessionComponent().inject(this)
      }
    }
    

    在我看来,这不是解决这个问题的好办法。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Vairavan    7 年前

    尝试使用Dagger Android,效果不错。此外,appsignup并不真正需要模块。@用@singleton注入constructor()就可以了。在引擎盖下,它使用子组件。

    @Module
    abstract class AppModule {
    
        @Module
        companion object {
    
            @JvmStatic
            @Provides
            @Singleton
            fun providesAppSignUp() = AppSignUp()
    
        }
    }
    
    @Singleton
    @Component( modules = [AndroidSupportInjectionModule::class, ActivityBindingModule::class, AppModule::class] )
    interface AppComponent : AndroidInjector<MainApplication>
    
    @Module
    interface ActivityBindingModule {
    
        @UserScope
        @ContributesAndroidInjector( modules = [MainActivityModule::class] )
        fun mainActivity() : MainActivity
    }
    
    @Module
    abstract class MainActivityModule {
    
        @Module
        companion object {
    
            @JvmStatic
            @Provides
            @UserScope
            fun providesUserSession() = UserSession()
        }
    }
    
    class UserSession
    
    class AppSignUp
    
    @Scope
    annotation class UserScope
    
    class MainApplication : DaggerApplication() {
    
        @Inject
        lateinit var appSignUp : AppSignUp
    
        override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
            return DaggerAppComponent.builder().build()
        }
    
    }
    
    class MainActivity : DaggerAppCompatActivity() {
    
        @Inject
        lateinit var appSignUp: AppSignUp
    
        @Inject
        lateinit var appSignUp1: AppSignUp
    
        @Inject
        lateinit var userSession: UserSession
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    }