Кинжал с Android: как мне вставлять текущий контекст?

Вернувшись, когда я использовал RoboGuice, мне удалось конструктор внедрить Context в мои классы, и RoboGuice выберет соответствующий контекст (у инъекций в Activity будет контекст Activity, впрыски в приложении будут иметь текущий контекст приложения, внедряется в Фрагмент будет иметь контекст активности фрагмента и т.д.).

Есть ли аналогичный метод для достижения этого с помощью кинжала?

public class Thing {
    @Inject
    public class Thing(Context context){
       // if i'm injected in an Activity, I should be the current activity context
       // if i'm injected in an Fragment, I should be the fragment activity context
       // if i'm injected in a Service, I should be the service context
       // etc...
    }
}

Ответ 1

Кинжал не знает об Android. Или что-нибудь, действительно. Если вы хотите что-то ввести, вы должны сказать об этом Кинжал.

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

/**
 * Allow the application context to be injected but require that it be annotated with
 * {@link ForApplication @Annotation} to explicitly differentiate it from an activity context.
 */
@Provides @Singleton @ForApplication Context provideApplicationContext() {
  return application;
}

Edit

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

Единственный способ сделать это - использовать factory, который позволяет указать контекст, с которым будет создан объект.

public final class ThingFactory {
  private final Foo foo;
  private final Bar bar;

  @Inject public ThingFactory(Foo foo, Bar bar) {
    this.foo = foo;
    this.bar = bar;
  }

  public Thing get(Context context) {
    return new Thing(context, foo, bar);
  }
}