Объяснение прицелов Dagger 2

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

Я много читал о кинжале, но до сих пор не могу понять некоторые детали.

Я создал свой ApplicationComponent, и он выглядит так

@Singleton
@Component(modules = {
        ApplicationModule.class,
        ThreadingModule.class,
        NetworkModule.class,
        DatabaseModule.class,
        ServiceModule.class,
        ParseModule.class,
        PreferencesSessionModule.class})

public interface ApplicationComponent {
    void inject(BaseActivity baseActivity);
    void inject(MainAppActivity mainAppActivity);
    void inject(BaseFragment baseFragment);
}

И он отлично работает, все инжектится правильно, но теперь я хочу углубиться в dagger API и использовать Custom Scope

У меня есть модуль под названием PermissionModule, он используется для версий Android M.

@PerActivity
@Module
public class PermissionModule {
    @Provides
    @PerActivity
    PermissionController providePermissionController(Activity activity) {
        return new PermissionManager(activity);
    }
}

И я хочу, чтобы он был введен в мою деятельность и находился в памяти только тогда, когда активность также находится в памяти (жизненный цикл активности)

@PerActivity
@Component(modules = {
        ActivityModule.class,
        PermissionModule.class
})
public interface ActivityComponent {
    Activity activity();

    void inject(BaseActivity baseActivity);

    PermissionModule permissionModule();
}

My ActivityComponent

@PerActivity
@Component(modules = {
        ActivityModule.class,
        PermissionModule.class
})
public interface ActivityComponent {
    Activity activity();

    void inject(BaseActivity baseActivity);

    PermissionModule permissionModule();
}

И мой BaseActivity

public abstract class BaseActivity extends AppCompatActivity implements SpiceManagerProvider, NetworkRequestsExecutor {
    // Dependencies are injected by ApplicationComponent
    @Inject
    protected ApplicationSettingsManager mApplicationSettingsManager;
    @Inject
    protected SpiceManager mSpiceManager;
    @Inject
    protected ScheduledThreadPoolExecutor mPoolExecutor;

    !!!!!!
    Should be injected by activity component 
    @Inject
    protected PermissionController mPermissionController;

А в onCreate()

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Injecting dependencies
        MyApplication application = MyApplication.get(this);
        application.getApplicationComponent().inject(this);
        DaggerActivityComponent.builder().activityModule(new ActivityModule(this)).build().inject(this);
        mPermissionController.requestPermission(Manifest.permission.ACCESS_FINE_LOCATION);
        mPermissionController.requestPermission(Manifest.permission.CAMERA);
        super.onCreate(savedInstanceState);
    }

я получил ошибку

PermissionController не может быть предоставлен без аннотированного метода @Provides- или @Produces. .ui.activities.base.BaseActivity.mPermissionController

Что не так в моем коде?

Также не создавать новый вопрос, связанный с этой темой.

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


person Community    schedule 01.04.2016    source источник


Ответы (3)


поэтому проблема в том, что вы сначала вызываете метод инъекции ApplicationComponent

application.getApplicationComponent().inject(this);

который пытается внедрить все члены, включая PermissionController. Но ApplicationComponent не может этого обеспечить, и именно на это жалуется Dagger.

Решение состоит в том, чтобы вызвать метод inject() компонента ActivityComponent.

Скорее всего, в какой-то момент вам понадобятся зависимости, предоставляемые ApplicationComponent. Чтобы заархивировать это, вам нужно объединить два компонента. Dagger предоставляет для этого два способа: подкомпоненты и зависимости компонентов

При использовании зависимостей компонентов в методе onCreate() вашей Activity будет что-то вроде этого:

 DaggerActivityComponent
            .builder()
            .applicationComponent(application.getApplicationComponent())
            .activityModule(new ActivityModule(this))
            .build().inject(this);

когда вы меняете свои компоненты, чтобы они выглядели примерно так:

@PerActivity
@Component(
    dependencies = ApplicationComponent.class, 
    modules = {
        ActivityModule.class,
        PermissionModule.class
    }
)
public interface ActivityComponent {
    ...
}

обратите внимание, что вам нужно явно указать зависимости в ApplicationComponent, когда вам это нужно в ActivityComponent (или любых инжекторах)

person nosyjoe    schedule 01.04.2016
comment
Спасибо за ответ, единственное, что мне интересно, это чистый способ сделать это? Или может есть другой вариант? - person ; 01.04.2016
comment
как я уже упоминал, вы можете сделать это и с подкомпонентами. но кроме объединения графа зависимостей и использования результата для разрешения зависимостей, я не думаю, что есть более чистое решение. область видимости также имеет смысл только в том случае, если у вас есть только один граф объектов. в противном случае вы можете получить несколько экземпляров для области. - person nosyjoe; 05.04.2016

Если есть какая-либо зависимость от родительского компонента (например, @Componenet (model=AppModel.class) public interface appComponent...), которую вы хотите использовать в дочернем компоненте (@ActivityScope @Component (DEPENDENCY=APPCOMPONENT.class, model= ActivityModel .class) общедоступный интерфейс activityComponenet...), вам нужно выставить его в родительском компоненте. Только открытые зависимости доступны нижестоящим (в дочерних компонентах). Вы делаете это, написав метод из appModel, который должен обеспечить зависимость ниже по течению в интерфейсе appComponenet. Имя метода не обязательно должно совпадать с именем метода в appModel, учитывается только тип возвращаемого значения.

person Marko Kostic    schedule 26.08.2016

По поводу вашей путаницы с прицелами "Кинжал", настоящим уточняю некоторые выводы относительно прицелов

  • Каждый раз, когда тот же компонент внедряет службу без области действия, создается новый экземпляр службы.
  • При первом внедрении сервиса с областью действия @Singleton он создается и кэшируется внутри внедряющего компонента, а затем тот же самый экземпляр будет использоваться при внедрении в другие поля того же типа тем же компонентом.
  • Пользовательские области действия функционально эквивалентны предопределенной области @Singleton.
  • Внедрение служб с ограниченной областью действия является потокобезопасным.

Если вы действительно хотите четко понять, как внутренне Dagger использует singleton и custom scope , следуйте этой статье Прицелы Dagger 2: как это работает внутри

person Abhishek Luthra    schedule 01.04.2018
comment
очень хороший ответ, только проблема в том, что это грубый плагиат!!! Чувак, копипаст чужой работы и репост на Медиуме как свой... это просто низко. Вот источник, датированный за 2 года до вашего: techyourchance.com/dagger-2-scopes -демистифицировано Судите сами. - person Mardann; 10.03.2019