Обеспечение только одного экземпляра для каждой области в Dagger2

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

Область Singleton по умолчанию уже работает таким образом. Независимо от того, в скольких местах вы внедряете один и тот же объект, давайте назовем его GlobalInstance, метод GlobalInstance provideGlobalInstance(), создающий его, будет вызываться один и только один раз.

С другой стороны, если я определяю пользовательскую область видимости, например @SessionScope, и внутри некоторого SessionModule создаю метод User provideUser(), этот метод (и, соответственно, конструктор new User()) будет вызываться столько раз, сколько я внедряю User. Независимо от того, использую ли я один и тот же экземпляр модуля каждый раз, User provideUser() вызывается для каждого @Inject User mUser, который у меня есть в моем коде, в результате чего получается несколько экземпляров вместо одного «синглтона» с ограниченной областью действия.

Есть ли какой-то четкий способ добиться этого, используя обычный Dagger API. Один из способов сделать это - иметь ленивые геттеры внутри класса модуля, но это не очень чистый способ сделать это.


person SadClown    schedule 10.02.2017    source источник
comment
Вы должны использовать один и тот же компонент, чтобы убедиться, что вы вводите экземпляр, принадлежащий данному компоненту.   -  person EpicPandaForce    schedule 10.02.2017
comment
Итак, вместо того, чтобы сохранять модуль, я должен каким-то образом сохранить весь компонент, верно? Каковы наилучшие практики для этого? Кэш некоторых статических/глобальных компонентов?   -  person SadClown    schedule 10.02.2017
comment
Да, обычно да. Я видел static для области @Singleton на уровне приложения и onRetainCustomNonConfigurationInstance() для действия. Map<Something, Object> иначе где хранят компонент на какой-то ключ в карте   -  person EpicPandaForce    schedule 10.02.2017
comment
Спасибо, вы мне помогли :)   -  person SadClown    schedule 10.02.2017
comment
Map<Something, Object> отлично, теперь ищем компоненты почти так же, как это делает Service Locator. Хотя, я не могу придумать лучшего подхода. Теперь, когда вопросу исполнилось 4 года, видели ли вы лучшую реализацию?   -  person Farid    schedule 18.03.2021


Ответы (1)


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

Это означает, что у вас может быть два варианта методов @Provides в SessionModule:

  • @Provides @SessionsScope — предоставляет «сеансовые синглтоны» (подробнее об этом позже)
  • @Provides - предоставляет новый объект при каждой инъекции

Обратите внимание, что термин "синглтон" имеет некоторую двусмысленность, когда мы говорим о Dagger, поэтому я предпочитаю использовать термин "объекты с ограниченной областью действия". Когда объект с областью видимости внедряется с помощью Dagger в первый раз, компонент кэширует свой экземпляр и возвращает его при каждой последующей инъекции, ВЫПОЛНЕННОЙ ТЕМ ЖЕ КОМПОНЕНТОМ.

Для получения дополнительной информации вы можете прочитать этот пост: Разоблачение прицелов Android Dagger 2

person Vasiliy    schedule 10.02.2017
comment
Я предположил, что пользовательские области действия ничем не отличаются от предоставляемых Singleton, но, как я описал, у меня другое поведение. Похоже, проблема в том, что EpicPandaForce объяснил в комментарии: я должен использовать не один и тот же модуль, а целый компонент, если я не хочу, чтобы методы Provide*() вызывались более одного раза для каждой области. - person SadClown; 10.02.2017
comment
@SadClown, пожалуйста, прочитайте сообщение в блоге, на которое я ссылался, - оно подробно объясняет эти отношения. На github также есть учебное приложение, в котором показан один из возможных подходов к работе с компонентами. - person Vasiliy; 10.02.2017
comment
Извините, если я выгляжу грубым, но я просмотрел пост и не нашел своего ответа. Но я решил свою проблему, объединив ваш ответ и ответ EpicPandaForce. Спасибо. - person SadClown; 10.02.2017
comment
@SadClown, я не имел в виду, что вы грубы, но в ответ можно опубликовать не так много информации. Рад, что вы нашли решение. - person Vasiliy; 10.02.2017
comment
Argh, мой плохой, есть намек на ответ в посте, которым вы поделились. Я нашел это в одном предложении, за которым как-то следил. - person SadClown; 10.02.2017