Skip to main content
Version: 4.2 - LTS

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.

With a string name:

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

Or with a type reference:

@Factory
class MyFactory(
@ScopeId(MyScope::class) 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.