Почему использование @Module.subcomponents лучше, чем установка подкомпонента с помощью метода родительского компонента?

Из документы:

Using @Module.subcomponents is better since it allows Dagger to detect if the subcomponent is ever requested. Installing a subcomponent via a method on the parent component is an explicit request for that component, even if that method is never called. Dagger can’t detect that, and thus must generate the subcomponent even if you never use it.

Кто-нибудь точно понимает, что это значит?

Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Лучшие практики использования Guice в ваших Java-проектах
Лучшие практики использования Guice в ваших Java-проектах
Guice от Google - это популярная система инъекции зависимостей для Java-приложений. Он помогает разработчикам создавать более ремонтопригодный,...
1
0
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

@Component(modules = YourModule.class)
public interface YourComponent {
  ClassA a();
  ClassB b();

  ExplicitSubcomponent createExplicitSubcomponent(Dep1 dep1, Dep2 dep2);
}

@Module(subcomponents = ImplicitSubcomponent.class)
public abstract class YourModule {
  @Binds ClassC classC(DefaultClassC classCImpl);
}

В приведенном выше примере у нас есть ClassA, ClassB и ClassC. Предположим, что из всего этого вам на самом деле нужен только ClassA: они на самом деле не зависят друг от друга, и вы на самом деле не используете подкомпоненты.

  • Dagger реализует привязку для ClassA и транзитивное закрытие зависимостей ClassA, и это хорошо, потому что вам это нужно! Вы помещаете его в интерфейс компонента, чтобы Dagger мог создавать для вас реализации, включая все зависимости ClassA.
  • Dagger реализует привязку для ClassB, в которой нет необходимости, но Dagger не может сказать: он знает только, что b() определено, так что кто-нибудь может когда-нибудь вызвать и попросить ClassB. Dagger не имеет представления о том, вызывает ли кто-либо b(), поэтому он должен создавать и ссылаться на фабричные реализации для ClassB и всего, от чего ClassB зависит транзитивно.
  • Dagger не реализует привязку для ClassC, потому что даже если вы связали его, никто не запрашивает его. Он недоступен в интерфейсе, и никто не запрашивает его внутри, поэтому Dagger может безопасно его опустить.

Это иллюстрирует философию Dagger по компиляции только того, что доступно из самого интерфейса компонента. Это относится и к подкомпонентам:

  • Dagger создает реализацию для ExplicitSubcomponent, поскольку, как и в случае с ClassB, вы привязываете его к интерфейсу. Кто-то может попросить об этом.
  • Dagger не создает реализацию для ImplicitSubcomponent, пока он не будет доступен из ClassA или ClassB. Как только вы это сделаете, так и будет. Если никто не запрашивает ImplicitSubcomponent, Dagger не генерирует для него код.

Конечно, если вы обрезаете свою сборку с помощью Proguard или какого-либо другого статического анализатора, эти инструменты могут удалить ненужные классы или методы. Однако в этот момент вы выполняете работу по генерации кода подкомпонента, вы выполняете работу по его компиляции в байт-код, а затем Proguard выполняет работу по его удалению. В больших проектах намного эффективнее, если вы избегаете компиляции подкомпонента, пока не узнаете, что он вам нужен, что позволяет Module.subcomponents.

Спасибо, что нашли время написать такой отличный ответ! Я случайно посмотрел сегодня это видео, которое на самом деле также отвечает на этот вопрос, оставлю ссылку здесь для будущих читателей youtube.com/watch?v=wCvXe2LsN5o&feature=youtu.be&t=1635

Fred Porciúncula 09.04.2019 19:35

Другие вопросы по теме