Кинжал 2: введите 2 разных прицела в один объект - PullRequest
0 голосов
/ 20 ноября 2018

Прежде чем кто-то начнет отмечать этот вопрос как дублированный, позвольте мне сказать, что я уже проверил эту запись , но это не решило мою проблему.

Как следует из названия, мне нужноввести два объекта из разных областей в другой объект.Допустим, у нас следующая ситуация:

У нас есть экран, на котором мы позволяем пользователю зарегистрироваться, а затем, на том же экране, мы выполняем некоторые операции на основе пользовательского сеанса (например, выполняем некоторую синхронизацию).

Для моего проекта я планировал использовать субкомпоненты.У меня есть следующий (упрощенный) код, основанный на этой публикации :

@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);
  }
}

Теперь, чтобы упростить задачу, скажем, у меня есть компонент (действие,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.Итак, вопрос в том, как я могу решить эту проблему?Есть ли в Dagger какие-либо функции для этого сценария?

До сих пор я мог думать только о следующем решении:

Сделать UserSessionSync независимым от среды Dagger и внутри

public class UserSessionSync {
  @Inject
  UserSessionSyncHelper userSessionSyncHelper;

  public UserSessionSync(){
    MyApplication.getUserSessionComponent().inject(this)
  }
}

ВПо моему мнению, это не очень хороший способ решить эту проблему.

1 Ответ

0 голосов
/ 20 ноября 2018

Пробовал с помощью Dagger-Android, отлично работает.Также модуль не нужен для AppSignUp.@Inject constructor () с @Singleton сделает это.Под капотом используются подкомпоненты.

@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)
    }
}
...