Dagger 2 Добавление подкомпонента к родительскому компоненту - PullRequest
0 голосов
/ 29 июня 2018

Привет, сообщество. У меня проблема с пониманием того, как кинжал 2 добавляет субкомпонент новым способом (добавлен в кинжал 2.7). Смотрите пример ниже:

@Component(modules = {AppModule.class, MainActivityBinder.class})
@Singleton
interface AppComponent
{
   inject(MyApplication _)
}

@Subcomponent(modules = ActivityModule.class)
interface ActivitySubcomponent
{
   inject(MainActivity _)

   @Subcomponent.Builder
   interface Builder
   {
      @BindInstance
      Builder activity(Activity activity)

      ActivitySubcomponent build();
   }
}

Начальный шаг: у меня AppComponent с является моим корневым компонентом, который обеспечивает AppModule синглетами (модернизация, охтп и т. Д.). В ActivitySubcomponent я предоставляю ActivityModule с зависимостями, указанными для этого действия. Теперь подкомпонент должен быть добавлен к AppComponent, поэтому по-новому я создаю указанный модуль с именем MainActivityBinder, который имеет аннотации @ Module.subcomponents с точкой, которая связывает подкомпонент, но у меня есть первая проблема, что должно быть в теле этого модуль связывания?

@Module(subcomponents = ActivitySubcomponent.class)
public class MainActivityBinder
{
  //what body of this class should be ??
}

Я знаю, что идея заключается в том, что я могу связывать субкомпонент или его конструктор. Второй вопрос, когда связывать строителя, а когда связывать подкомпонент? Например, мой ActivitySubcomponent требуемый контекст активности, поэтому я создаю конструктор, который предоставляет контекст для ActivityModule, в этом случае будет лучше предоставить в MainActivityBinder конструктор? Третий вопрос, как вызвать компоновщик компонентов и как получить подкомпонент для компонента приложения? В стандартной фабрике подкомпонентов я добавил к AppComponent метод, который возвращает подкомпонент, и я могу определить параметры (например, дать контекст действия, указанный ниже)

@Component(modules = {AppModule.class})
@Singleton
interface AppComponent
{
   ActivitySubcomponents newActivitySubcomponents(Activity activity);

   inject(MyApplication _);
}

// in MainActivity
appComponent.newActivitySubcomponents(this).build().inject(this);

Итак, добились ли вы такого поведения в новом методе добавления подкомпонентов?

1 Ответ

0 голосов
/ 30 июня 2018
  1. Ваш модуль MainActivityBinder может быть пустым, и должен быть, если у вас больше ничего нет с ним связать. Пустые (только для аннотаций) модули также полезны, когда вы используете только Module.includes, например, когда вы хотите хранить список модулей в одном месте, а не дублировать его среди нескольких компонентов. Атрибут subcomponents в аннотации достаточен для того, чтобы Кинжал понял, что вы пытаетесь сделать.

  2. Вы можете ввести FooSubcomponent или Provider тогда и только тогда, когда у него нет методов @BindsInstance или инстанцируемых модулей (которые Dagger не может создать). Если все ваши модули являются интерфейсами, абстрактными классами или модулями, имеющими общедоступные конструкторы с нулевым аргументом, то вы можете напрямую внедрить подкомпонент. В противном случае вы должны вместо этого ввести свой компонент субкомпонента.

  3. Вы можете добраться до вашего компоновщика подкомпонентов, создав метод, который возвращает его в вашем AppComponent, так же, как вы можете для любой привязки, существующей в графе:

    @Component(modules = {AppModule.class, MainActivityBinder.class})
    @Singleton
    interface AppComponent {
      ActivitySubcomponent.Builder activitySubcomponentBuilder();
    
      inject(MyApplication _)
    }
    

    Вы также можете ввести его в объект по вашему выбору.

    @Inject ActivitySubcomponent.Builder activitySubComponentBuilder;
    activitySubComponentBuilder.activity(this).build().inject(this);
    
    // You can also inject a Provider<ActivitySubcomponent.Builder> if you want,
    // which is a good idea if you are injecting this directly into your Application.
    // Your Application will outlive your Activity, and may need to inject several
    // instances of the Activity across application lifetime.
    @Inject Provider<ActivitySubcomponent.Builder> activitySubComponentBuilderProvider;
    activitySubComponentBuilderProvider.get().activity(this).build().inject(this);
    

Хотя, как представляется, нет особого преимущества для внедрения построителя подкомпонентов, когда вы можете с таким же легкостью вызывать метод компонента (либо для возврата Строителя, либо для возврата подкомпонента), есть несколько преимуществ для внедрения Строитель:

  • Dagger не может определить, вызываете ли вы метод для компонента, поэтому он генерирует и компилирует код, даже если ваш подкомпонент не используется. Dagger может сказать, пытаетесь ли вы когда-нибудь внедрить конструктор, поэтому, если нет вложений подкомпонента / построителя и нет методов, Dagger пропустит генерирование кода для подкомпонента.
  • Если ваша кодовая база достаточно велика, чтобы вам приходилось разбивать ее на разные цели для компиляции, метод фабричного метода может застать вас в некоторых циклах зависимостей, где компонент и модули вашего приложения зависят от всего, и вы можете добраться только до своего субкомпонент от самого компонента. Благодаря инжектируемым компоновщикам субкомпонентов у вас есть больше возможностей узнать, как добраться до вашего субкомпонента или компоновщика.
...