Skip to main content
Version: 4.1

Scopes in Koin Annotations

While using definitions and modules, you may need to define scopes for a particular space and time resolution.

Defining a Scope with @Scope

Koin allows the use of scopes. Please refer to Koin Scopes section for more details on basics.

To declare a scope with annotations, just use @Scope annotation on a class, like this

@Scope
class MyScopeClass

this will be equivalent of the following scope section:

scope<MyScopeClass> {

}

Else, if you need a scope name more than a type, you need to tag a class with @Scope(name = ) annotation, using name parameter:

@Scope(name = "my_scope_name")
class MyScopeClass

this will be the equivalent of

scope<named("my_scope_name")> {

}

Adding a definition in a Scope with @Scoped

To declare a definition inside a scope (defined or not with annotations), just tag a class with @Scope and @Scoped annotations:

@Scope(name = "my_scope_name")
@Scoped
class MyScopedComponent

This will generate the right definition inside the scope section:

scope<named("my_scope_name")> {
scoped { MyScopedComponent() }
}
info

You need both annotations to indicate the needed scope space (with @Scope) and the kind of component to define (with @Scoped)

Dependency resolution from a scope

From a scoped definition, you can resolve any definition from your inner Scope and from the parent scopes.

For example, the following case will work:

@Single
class MySingle

@Scope(name = "my_scope_name")
@Scoped
class MyScopedComponent(
val mySingle : MySingle,
val myOtherScopedComponent :MyOtherScopedComponent
)

@Scope(name = "my_scope_name")
@Scoped
class MyOtherScopedComponent(
val mySingle : MySingle
)

The component MySingle is defined as single definition, in the root. MyScopedComponent and MyOtherScopedComponent are defined in scope "my_scope_name". The dependencies resolution from MyScopedComponent is accessing the Koin root with MySingle instance, and MyOtherScopedComponent scoped instance from the current "my_scope_name" scope.

Resolving outside a Scope with @ScopeId (since 1.3.0)

You may need to resolve a component from another scope that is not directly accessible to your scope. For this, you need to tag your dependency with @ScopeId annotation to tell Koin to find this dependency in the scope of the given scope Id.

@Factory
class MyFactory(
@ScopeId("my_scope_id") val myScopedComponent :MyScopedComponent
)

The above code is equivalent is generated:

factory { Myfactory(getScope("my_scope_id").get()) }

This example shows that MyFactory component will resolve MyScopedComponent component from a scope instance with id "my_scope_id". This scope, created with id "my_scope_id" needs to be created with the right scope definition.

info

The MyScopedComponent component needs to be defined in a Scope section, and a scope instance needs to be created with id "my_scope_id".

Scope Archetype Annotations

Koin Annotations provides predefined scope archetype annotations for common scope patterns, eliminating the need to manually declare scope types. These annotations combine scope declaration and component definition in a single annotation.

Android Scope Archetypes

For Android development, you can use these predefined scope annotations:

@ActivityScope

Declare a component in an Activity scope:

@ActivityScope
class ActivityScopedComponent(val dependency: MyDependency)

This generates:

activityScope {
scoped { ActivityScopedComponent(get()) }
}

Usage: The tagged class is meant to be used with Activity and the activityScope function to activate the scope.

@ActivityRetainedScope

Declare a component in an Activity Retained scope (survives configuration changes):

@ActivityRetainedScope
class RetainedComponent(val repository: MyRepository)

This generates:

activityRetainedScope {
scoped { RetainedComponent(get()) }
}

Usage: The tagged class is meant to be used with Activity and the activityRetainedScope function to activate the scope.

@FragmentScope

Declare a component in a Fragment scope:

@FragmentScope
class FragmentScopedComponent(val service: MyService)

This generates:

fragmentScope {
scoped { FragmentScopedComponent(get()) }
}

Usage: The tagged class is meant to be used with Fragment and the fragmentScope function to activate the scope.

Core Scope Archetypes

@ViewModelScope

Declare a component in a ViewModel scope. This annotation is Kotlin Multiplatform (KMP) compatible and works with both Android ViewModels and Compose Multiplatform ViewModels:

@ViewModelScope
class ViewModelScopedRepository(val apiService: ApiService)

@ViewModelScope
class ViewModelScopedUseCase(
val repository: ViewModelScopedRepository,
val analytics: AnalyticsService
)

This generates:

viewModelScope {
scoped { ViewModelScopedRepository(get()) }
scoped { ViewModelScopedUseCase(get(), get()) }
}

Usage: The tagged class is meant to be used with ViewModel and the viewModelScope function to activate the scope.

KMP Support: Works seamlessly across all Kotlin Multiplatform targets including Android, iOS, Desktop, and Web platforms where ViewModels are used.

Using Scope Archetypes

Scope archetype annotations work seamlessly with regular Koin scoping:

// Regular components
@Single
class GlobalService

// Scoped components using archetypes
@ActivityScope
class ActivityService(val global: GlobalService)

@FragmentScope
class FragmentService(
val global: GlobalService,
val activity: ActivityService
)

Combining with Function Definitions

Scope archetypes can also be used on functions within modules:

@Module
class MyModule {

@ActivityScope
fun activityComponent(dep: MyDependency) = MyActivityComponent(dep)

@FragmentScope
fun fragmentComponent(dep: MyDependency) = MyFragmentComponent(dep)
}
info

Scope archetype annotations automatically create the appropriate scope definition and scoped component declaration, reducing boilerplate code for common scope patterns.