Кинжал @ Многоразовый прицел против @Singleton

Из руководства пользователя:

Иногда вы хотите ограничить число случаев создания экземпляра класса @Inject или вызова метода @Provides, но вам не нужно гарантировать, что один и тот же экземпляр используется в течение срока жизни любого конкретного компонента или подкомпонента.

Зачем мне использовать это вместо @Singleton?

1 ответ

Решение

Используйте @Singleton, если вы полагаетесь на поведение и гарантии синглтона. Используйте @Reusable, если объект будет только @Singleton по соображениям производительности.


Привязки @Rusable имеют гораздо больше общего с привязками с незаданной областью, чем привязки @Singleton: вы говорите Dagger, что у вас все получится, если вы создадите совершенно новый объект, но если уже создан удобный объект, Dagger может использовать его. Напротив, объекты @Singleton гарантируют, что вы всегда будете получать один и тот же экземпляр, который может быть намного дороже в реализации.

В общем, Dagger и DI предпочитают объекты с незаданной областью: создание нового объекта - это отличный способ сохранить состояние в жестком состоянии и позволяет собирать мусор как можно скорее, как зависимый объект. Кинжал показывает некоторые из этих встроенных предпочтений: В Кинжале объекты с незаданной областью могут быть смешаны с любым компонентом или модулем, независимо от того, аннотирован ли компонент компонентом. Этот тип привязки с незаданной областью полезен также для объектов без состояния, таких как внедряемые (mockable) служебные классы и реализации стратегии, команд и других шаблонов полиморфного поведения: объекты должны быть связаны глобально и внедрены для тестирования / переопределений, но экземпляры этого не делают. сохранить любое состояние и недолгим или одноразовым.

Однако в Android и других средах с ограниченной производительностью и памятью создание многих временных объектов противоречит рекомендациям по производительности, поскольку создание экземпляров и сборка мусора являются более дорогостоящими процессами, чем на настольных виртуальных машинах. Это приводит к прагматическому решению пометить объект @Singleton не потому, что важно всегда получать один и тот же экземпляр, а просто для сохранения экземпляров. Это работает, но семантически слабо, а также имеет последствия для памяти и скорости: ваш недолговечный объект утилит или шаблон стратегии теперь должен существовать до тех пор, пока существует ваше приложение, и доступ к нему должен осуществляться через двойную проверку блокировки, иначе вы рискуете нарушить гарантию @Singleton "только один экземпляр" (в этом нет необходимости). Это может быть источником повышенного использования памяти и накладных расходов на синхронизацию.

Компромисс заключается в связываниях @Reusable, которые имеют свойства сохранения экземпляра, такие как @Singleton, но исключаются из правила @Component сопоставления контекста, как и привязки с незаданной областью, что дает вам больше гибкости в том, где вы их устанавливаете. (См. Тесты.) Они имеют срок службы только до тех пор, пока самый внешний компонент, который использует их напрямую, будет случайным образом использовать экземпляр от предка для сохранения в дальнейшем, но без двойной проверки блокировки для экономии затрат на создание. Наконец, и самое главное, они дают вам и будущим разработчикам сигнал о том, как этот класс предназначен для использования.

Короче говоря, @Singleton будет работать, но @Reusable имеет некоторые явные преимущества в производительности, если все дело в производительности, а не в жизненном цикле объекта.

Другие вопросы по тегам