Подтвердить что ты не робот

Метод инъекции с использованием кинжала 2

Мне не удалось найти хорошее объяснение/пример при инъекции метода с помощью кинжала 2. Может ли кто-нибудь помочь мне понять?

Пример:

@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
    mPan.add(pasta);
    mPan.add(sauce);
    return mPan.cookDinner();
}

Итак, если я аннотирую свой метод с помощью @Inject, могу ли я предположить, что аргументы в сигнатуре метода будут введены с определенными объектами из графа объектов? Как я могу использовать этот метод в моем коде? Он все равно ожидает, что я поставлю все аргументы, когда я вызову метод, какой вид поражения цели.

UPDATE:

Итак, из того, что я понимаю, объект Dinner будет доступен, если я назову DinnerComponent.dinner(), если мой DinnerComponent настроен следующим образом:

@Component(modules = DinnerModule.class)
public interface DinnerComponent {
    Dinner dinner();
}

и мой DinnerModule настроен следующим образом:

@Module
public class DinnerModule {
    public DinnerModule() {}

    @Provides
    Pasta providePasta() { return new Pasta(); }

    @Provides
    Sauce provideSauce() { return new Sauce(); }
}

Что произойдет, если я хочу, чтобы мой ужин был обжарен? Итак, введем этот метод:

@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
    mPan.add(pasta);
    mPan.add(sauce);
    return mPan.fryDinner();
}

Как я могу указать в компоненте, который является обедом?

4b9b3361

Ответ 1

Одно фундаментальное отличие от инъекции метода, которое отличается от того, как вы его используете, заключается в том, что инъекция метода - это еще один способ для кинжала отправлять зависимости при построении или инъекции объекта DI-ready, что означает, что @Inject-аннотированные методы должны быть вызваны кинжалом один раз при построении, а не из вашего собственного кода. Это делает очень маловероятным, чтобы вы @Inject -незаменили makeDinner, fryDinner или любой другой метод, который имеет значимые побочные эффекты или возвращаемые значения. Вместо этого обработайте инъекцию метода как возможность пост-факто для инъекций в стиле конструктора.

public class Chef {
  private Provider<Pasta> mPastaProvider;
  private Sauce mSauce;

  @Inject
  public void registerIngredients(     // can be named anything
      Provider<Pasta> pastaProvider,
      Sauce sauce) {                   // T and Provider<T> both work, of course
    mPastaProvider = pastaProvider;
    mSauce = sauce;
  }

  /* [email protected] */ public Dinner cookDinner() {
    mPan.add(mPastaProvider.get());
    mPan.add(mSauce);
    return mPan.cookDinner();
  }

  /* [email protected] */ public Dinner fryDinner() {
    mPan.add(mPastaProvider.get());
    mPan.add(mSauce);
    return mPan.fryDinner();
  }
}

В этом случае, когда вы запрашиваете инъекцию у шеф-повара, Кинжал увидит @Inject-аннотированный метод и вызовет его. Если у вас нет конструктора @Inject-annotated или @Provides, вы не сможете получить шеф-повар прямо из вашего компонента, но вы можете создать метод void для компонента, который получает построенный экземпляр Chef и который использует инъекцию полей и методов, чтобы обеспечить шеф-повару ингредиентами (или поставщиками ингредиентов), которые им могут понадобиться. (Подробнее см. В документах @Component и MembersInjector.)

Обратите внимание, что ни в коем случае не отображается Dinner на графе объектов! Добавление @Inject в конструктор говорит Кинжалу, что он может использовать этот конструктор, чтобы сделать объект доступным на графе объектов, но добавление @Inject к методу или полю просто говорит кинжалу, что как часть процесса инъекции оно должно заполнить это поле или вызвать этот метод с данными зависимостями. Если вы хотите сделать ужин на графике объекта, вам нужно будет @Inject-аннотировать конструктор Dinner или поместить метод @Provides или @Binds в модуль, который вы подаете в компонент.

Зачем вам это использовать? Рассмотрим случай, когда объекты создаются рефлексивно (например, "Действия, фрагменты" и "Виды в Android" или "Сериализуемые объекты" ), где вы предпочитаете не открывать поля @Inject. В этих случаях вы можете обойти ограничения конструктора, если ваша инъекция произойдет в поле. Точно так же, хотя я и не пробовал этого, вы могли бы воспользоваться иерархией классов, чтобы отметить метод интерфейса с помощью @Inject, гарантируя, что независимо от того, находитесь ли вы в контексте DI, вы можете передать определенные зависимости объекту как часть их подготовка.

Ответ 2

Аннотирование метода с помощью @Inject дает инструкции Dagger для выполнения этого метода сразу после создания объекта - сразу после вызова конструктора. Это полезно, когда вам нужен полностью построенный объект для чего-то. Существует пример ввода метода в в этой статье.

Вы правы, говоря, что параметры этого метода будут предоставлены кинжалом, поэтому вы не должны сами называть этот метод.