← Назад к вопросам

Что такое factory в Koin?

2.2 Middle🔥 211 комментариев
#Dependency Injection

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Factory в Koin?

В Koin — популярной библиотеке для dependency injection (DI) на Kotlin — Factory — это особый тип определения (definition), который создаёт новый экземпляр зависимости при каждом запросе, вместо того чтобы предоставлять один и тот же экземпляр (singleton).

Ключевая разница: Factory vs Single

Основное отличие между factory и single в Koin заключается в жизненном цикле предоставляемого объекта:

  • single: Объявляет синглтон. Koin создаёт экземпляр один раз при первом запросе и затем возвращает этот же экземпляр на все последующие запросы в рамках всего скоупа (обычно всего приложения).
  • factory: Объявляет фабрику. Koin создаёт и возвращает новый экземпляр объекта при каждом вызове get() или внедрении зависимости.

Для чего нужен Factory?

Использование factory целесообразно в следующих сценариях:

  1. Объекты с коротким жизненным циклом: Когда вам нужен новый экземпляр для каждой операции (например, ViewModel для каждого экрана, Presenter, объект-состояние для конкретной задачи).
  2. Неизменяемое состояние: Если объект содержит данные, специфичные для конкретного контекста, и их не следует разделять между разными частями приложения.
  3. Избегание утечек памяти: Предотвращение ситуаций, когда синглтон необоснованно держит ссылки на контексты (например, Activity), что может приводить к утечкам памяти.
  4. Упрощение тестирования: Новый экземпляр на каждый инъекцию часто проще изолировать в unit-тестах.

Синтаксис и пример использования

Объявление factory в модуле Koin практически идентично объявлению single, но использует ключевое слово factory.

// Объявление модуля
val appModule = module {
    // Single: один репозиторий на всё приложение
    single<DataRepository> { DataRepositoryImpl() }

    // Factory: новый Presenter для каждого экрана/вызова
    factory<MainPresenter> { (view: MainView) -> MainPresenter(view, get()) } // get() внедрит DataRepository

    // Factory для простого объекта
    factory { NetworkService() } // Новый NetworkService каждый раз
}

Использование в коде:

class MainActivity : AppCompatActivity(), MainView {

    // Инъекция через фабрику: каждый раз будет создан новый MainPresenter
    private val presenter: MainPresenter by inject { parametersOf(this) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Работа с presenter
    }
}

// Или прямые вызовы:
val presenter1: MainPresenter = getKoin().get() // Создаст новый экземпляр
val presenter2: MainPresenter = getKoin().get() // Создаст ЕЩЁ ОДИН новый экземпляр
// presenter1 != presenter2

Параметры и Factory

Одним из мощных аспектов factory является удобная работа с параметрами (parameters). Поскольку фабрика создаёт объект при каждом запросе, она может принимать динамические параметры для его конфигурации.

val module = module {
    factory { (id: Int, name: String) -> UserComponent(id, name) }
}

// Использование с параметрами
val userComponent = getKoin().get<UserComponent> { parametersOf(42, "John") }

Важные нюансы

  • Отсутствие управления жизненным циклом: Koin не отслеживает экземпляры, созданные через factory. После инъекции их жизненный циклом управляет получатель (например, Activity или Fragment). Когда получатель уничтожается, уничтожается и зависимость (если на неё больше нет ссылок).
  • Производительность: Постоянное создание новых объектов может быть менее эффективным, чем использование синглтона, поэтому важно выбирать тип определения осознанно.
  • Связка со скоупами: factory часто используют вместе с скоупами (scopes). Например, вы можете объявить factory внутри скоупа viewModel или кастомного скоупа экрана, чтобы гарантировать создание новых экземпляров в рамках этого скоупа, но потенциально повторно использовать их внутри него (хотя для этого чаще используют scoped).

Итог

Factory в Koin — это механизм для предоставления нового экземпляра зависимости при каждом запросе, в отличие от single, который предощает единственный экземпляр. Это фундаментальная концепция для управления жизненным циклом объектов в приложении, которая позволяет гибко разделять зависимости с общим состоянием (через single) и данные, специфичные для конкретного контекста или операции (через factory). Правильное комбинирование этих подходов лежит в основе создания чистой, тестируемой и эффективной архитектуры Android-приложения с использованием Koin.