Dagger 2 Activity context / ApplicationContext модули

Я борюсь с кинжалом 2, чтобы понять, как я могу передать тот или иной контекст в соответствии с моими потребностями. - Сначала у меня есть ApplicationModule с аннотацией @Singleton, поскольку он предоставляет объекты высокого уровня, такие как объект веб-службы, модель ..., как правило, эти объекты передаются ApplicationContext (поскольку y должен существовать в течение всего времени жизни приложения)

@Singleton
@dagger.Component(modules = {
    AppModule.class
})
public interface AppComponent {
        void inject(MyApp application);
        Model model();
        Context context();<--- should provide the application Context for the Object above (model)
...

реализация выглядит так

@dagger.Module
public class AppModule {

    private final Application app;
    public ApplModule(Application app) {
        this.app = app;
    }

    @Provides
    @Singleton
    Model provideModel(Bus bus) {
        return new Model(bus);
    }

    @Provides
    @Singleton
    Context provideApplicationContext() {
        return app.getApplicationContext();
    }
...
  • во-вторых, у меня есть компонент Activity Scope, в котором я предоставляю текущую активность и различные представления, которым нужен контекст.

      @ActivityScope
        @Component(
                dependencies = AppComponent.class
                , modules = {ActivityModule.class}
        )
        public interface ActivityComponent {
            void inject(MyActivity activity);
            Context context(); <---should provide the activity's context
            MyView homeView(); <----takes a Context as a contructor parameter
    

    @Module общедоступный класс ActivityModule {закрытая конечная активность Activity;

    public ActivityModule(Activity activity) {
    
        this.activity = activity;
    }
    
    @Provides
    @ActivityScope
    public Activity activity() {
        return activity;
    }
    
    
    @Provides
    @ActivityScope
    @Named("viewcontext") <----- if I removed this I get an error from Dagger
    public Context context() {
        return activity;
    }
    
    @Provides
    @ActivityScope
    MyView provideZeView(Bus bus, Model model) { <---- previously receiving the ApplicationContext as a parameter 
        MyView v = new MyView(activity, bus, model); <---- must pass the activity otherwise passing the Context reveived is the ApplicationContext
        return v;
    }
    

    Итак, вот мои вопросы:

  • Я использовал области видимости, чтобы иметь лучшую "детализацию" переданного, и я все еще получаю applicationContext
  • Если я удалю @Named qulifier, я получаю сообщение об ошибке
  • ранее представления были созданы другим модулем с зависимостью от ActivityModule, но все еще получали ApplicationContext

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


person gropapa    schedule 08.08.2015    source источник
comment
Учитывая, что у вас есть два Context, которые почти одинаковы, вам нужно указать на них @Named("application") и @Named("activity").   -  person EpicPandaForce    schedule 26.08.2015
comment
Хотя на самом деле вы можете просто не добавлять Context context() в свой компонент, а только в модуль, и это тоже будет работать!   -  person EpicPandaForce    schedule 26.08.2015
comment
Поскольку Dagger выполняет инъекцию на основе типа, имеющего два метода, которые предоставляют класс Context, может вызвать ошибку, поэтому хорошие ребята включили аннотацию @Named ().   -  person fakataha    schedule 28.09.2015


Ответы (2)


вы можете использовать такие квалификаторы. в двух отдельных файлах определите следующее:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityContext {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {
}

тогда в вашем ActivityModule сделайте это:

@Provides
@ActivityScope
@ActivityContext
public Context context() {
    return activity;
}

и аналогично в вашем модуле приложения сделайте это:

 @Provides
    @Singleton
@ApplicationContext
    Context provideApplicationContext() {
        return app.getApplicationContext();
    }

теперь у нас есть способ запросить любой тип контекста, который нам нужен, на основе квалификаторов @ApplicationContext и @ActivityContext.

так, например, в своей деятельности вы можете сделать это:

  @Inject @ApplicationContext
    Context c;

который будет внедрять контекст приложения.

а в модуле вы можете сделать это, например:

  @Provides
    @ActivityScope
    LoginPresenter provideLoginPresenter(@ActivityContext Context context) {
        return new LoginPresenter(context);
    }

для обеспечения контекста деятельности. это всего лишь пример.

person j2emanue    schedule 30.05.2017

@Named - это требование, если вы хотите предоставить несколько объектов одного типа из вашего модуля.

Что касается вашего второго вопроса, что касается передачи правильного контекста Activity, вам необходимо иметь это в своем ActivityComponent:

Activity activity();
person IgorGanapolsky    schedule 28.12.2015