0
# Scoped Dependencies
1
2
Koin scopes provide lifecycle-aware dependency management, allowing you to create and manage dependencies that are tied to specific lifecycles like user sessions, request contexts, or feature workflows.
3
4
## Scope Basics
5
6
```kotlin { .api }
7
class Scope(
8
val scopeQualifier: Qualifier,
9
val id: ScopeID,
10
val isRoot: Boolean = false,
11
val _koin: Koin
12
) {
13
inline fun <reified T> get(
14
qualifier: Qualifier? = null,
15
noinline parameters: ParametersDefinition? = null
16
): T
17
18
inline fun <reified T> inject(
19
qualifier: Qualifier? = null,
20
mode: LazyThreadSafetyMode = KoinPlatformTools.defaultLazyMode(),
21
noinline parameters: ParametersDefinition? = null
22
): Lazy<T>
23
24
fun close()
25
}
26
27
typealias ScopeID = String
28
```
29
30
Scopes are containers for dependencies that share a common lifecycle. When a scope is closed, all its scoped instances are released.
31
32
## Defining Scoped Dependencies
33
34
### In Modules
35
36
```kotlin { .api }
37
fun Module.scope(qualifier: Qualifier, scopeSet: ScopeDSL.() -> Unit)
38
inline fun <reified T> Module.scope(scopeSet: ScopeDSL.() -> Unit)
39
40
class ScopeDSL(val scopeQualifier: Qualifier, val module: Module) {
41
inline fun <reified T> scoped(
42
qualifier: Qualifier? = null,
43
noinline definition: Definition<T>
44
): KoinDefinition<T>
45
46
inline fun <reified T> factory(
47
qualifier: Qualifier? = null,
48
noinline definition: Definition<T>
49
): KoinDefinition<T>
50
}
51
```
52
53
### Usage Examples
54
55
```kotlin
56
val userModule = module {
57
// Type-based scope
58
scope<UserSession> {
59
scoped<SessionData> { SessionDataImpl() }
60
scoped<UserPreferences> { UserPreferencesImpl(get()) }
61
scoped<ShoppingCart> { ShoppingCartImpl(get()) }
62
}
63
64
// Named scope
65
scope(named("request")) {
66
scoped<RequestContext> { RequestContextImpl() }
67
scoped<ValidationService> { ValidationServiceImpl(get()) }
68
}
69
}
70
```
71
72
## Creating and Managing Scopes
73
74
### Manual Scope Creation
75
76
```kotlin { .api }
77
fun Koin.createScope(scopeId: ScopeID, qualifier: Qualifier, source: Any? = null): Scope
78
fun Koin.getOrCreateScope(scopeId: ScopeID, qualifier: Qualifier, source: Any? = null): Scope
79
fun Koin.getScope(scopeId: ScopeID): Scope
80
fun Koin.getScopeOrNull(scopeId: ScopeID): Scope?
81
```
82
83
### Example Usage
84
85
```kotlin
86
class RequestHandler : KoinComponent {
87
fun handleRequest(requestId: String) {
88
// Create a request scope
89
val requestScope = getKoin().createScope(
90
scopeId = "request-$requestId",
91
qualifier = named("request")
92
)
93
94
try {
95
// Use scoped dependencies
96
val context = requestScope.get<RequestContext>()
97
val validator = requestScope.get<ValidationService>()
98
99
// Process request...
100
101
} finally {
102
// Always close scope to clean up
103
requestScope.close()
104
}
105
}
106
}
107
```
108
109
## KoinScopeComponent Integration
110
111
```kotlin { .api }
112
interface KoinScopeComponent : KoinComponent {
113
val scope: Scope
114
}
115
```
116
117
### Component Extension Functions
118
119
```kotlin { .api }
120
fun <T : Any> T.getScopeId(): ScopeID
121
fun <T : Any> T.getScopeName(): TypeQualifier
122
123
fun <T : KoinScopeComponent> T.createScope(
124
scopeId: ScopeID = getScopeId(),
125
source: Any? = null,
126
scopeArchetype: TypeQualifier? = null
127
): Scope
128
129
fun <T : KoinScopeComponent> T.getScopeOrNull(): Scope?
130
```
131
132
### Automatic Scope Management
133
134
```kotlin
135
class UserSession : KoinScopeComponent {
136
override val scope: Scope = createScope()
137
138
// These will be resolved from the session scope
139
private val sessionData: SessionData by scope.inject()
140
private val preferences: UserPreferences by scope.inject()
141
private val cart: ShoppingCart by scope.inject()
142
143
fun login(userId: String) {
144
sessionData.userId = userId
145
preferences.load(userId)
146
}
147
148
fun logout() {
149
scope.close() // Cleans up all scoped instances
150
}
151
}
152
153
class ShoppingFeature : KoinScopeComponent {
154
override val scope: Scope = createScope()
155
156
private val cart: ShoppingCart by scope.inject()
157
private val paymentService: PaymentService by scope.inject()
158
159
fun addToCart(item: Item) {
160
cart.add(item)
161
}
162
163
fun checkout() {
164
val items = cart.getItems()
165
paymentService.processPayment(items)
166
}
167
168
fun cleanup() {
169
scope.close()
170
}
171
}
172
```
173
174
## Scope Lifecycle Patterns
175
176
### Request Scope Pattern
177
178
```kotlin
179
val webModule = module {
180
scope(named("request")) {
181
scoped<RequestContext> { RequestContextImpl() }
182
scoped<UserSession> { UserSessionImpl(get()) }
183
scoped<DatabaseTransaction> { DatabaseTransactionImpl() }
184
}
185
}
186
187
class RequestProcessor : KoinComponent {
188
fun processRequest(request: HttpRequest): HttpResponse {
189
val scope = getKoin().createScope("req-${request.id}", named("request"))
190
191
return try {
192
val context = scope.get<RequestContext>()
193
val transaction = scope.get<DatabaseTransaction>()
194
195
// Process with scoped dependencies
196
handleRequest(request, context, transaction)
197
198
} finally {
199
scope.close()
200
}
201
}
202
}
203
```
204
205
### Feature Scope Pattern
206
207
```kotlin
208
val featureModule = module {
209
scope<OrderWorkflow> {
210
scoped<OrderBuilder> { OrderBuilderImpl() }
211
scoped<InventoryChecker> { InventoryCheckerImpl(get()) }
212
scoped<PaymentProcessor> { PaymentProcessorImpl(get()) }
213
}
214
}
215
216
class OrderWorkflow : KoinScopeComponent {
217
override val scope: Scope = createScope()
218
219
private val orderBuilder: OrderBuilder by scope.inject()
220
private val inventoryChecker: InventoryChecker by scope.inject()
221
private val paymentProcessor: PaymentProcessor by scope.inject()
222
223
suspend fun processOrder(orderData: OrderData): OrderResult {
224
val order = orderBuilder.build(orderData)
225
val available = inventoryChecker.check(order.items)
226
227
return if (available) {
228
paymentProcessor.process(order)
229
} else {
230
OrderResult.OutOfStock
231
}
232
}
233
234
fun complete() {
235
scope.close()
236
}
237
}
238
```
239
240
## Scope Linking and Hierarchy
241
242
### Parent-Child Scopes
243
244
```kotlin
245
class ParentScope : KoinScopeComponent {
246
override val scope: Scope = createScope()
247
248
fun createChildScope(): Scope {
249
return getKoin().createScope(
250
scopeId = "child-${System.currentTimeMillis()}",
251
qualifier = named("child"),
252
source = this
253
)
254
}
255
}
256
```
257
258
### Scope Dependencies
259
260
```kotlin
261
val hierarchicalModule = module {
262
scope(named("parent")) {
263
scoped<ParentService> { ParentServiceImpl() }
264
}
265
266
scope(named("child")) {
267
scoped<ChildService> {
268
// Can access parent scope dependencies
269
ChildServiceImpl(get<ParentService>())
270
}
271
}
272
}
273
```
274
275
## Error Handling
276
277
```kotlin { .api }
278
class ScopeNotCreatedException(message: String) : RuntimeException(message)
279
class ClosedScopeException(message: String) : RuntimeException(message)
280
```
281
282
### Safe Scope Operations
283
284
```kotlin
285
class SafeScopeHandler : KoinComponent {
286
fun safeGetFromScope(scopeId: ScopeID): UserService? {
287
return try {
288
val scope = getKoin().getScope(scopeId)
289
scope.get<UserService>()
290
} catch (e: ScopeNotCreatedException) {
291
null
292
} catch (e: ClosedScopeException) {
293
null
294
}
295
}
296
}
297
```
298
299
## Best Practices
300
301
### 1. Always Close Scopes
302
303
```kotlin
304
// Good - using try-finally
305
val scope = getKoin().createScope("temp", named("temp"))
306
try {
307
val service = scope.get<TempService>()
308
service.doWork()
309
} finally {
310
scope.close()
311
}
312
313
// Better - using use-like pattern
314
inline fun <T> withScope(
315
scopeId: ScopeID,
316
qualifier: Qualifier,
317
block: (Scope) -> T
318
): T {
319
val scope = getKoin().createScope(scopeId, qualifier)
320
return try {
321
block(scope)
322
} finally {
323
scope.close()
324
}
325
}
326
```
327
328
### 2. Scope Naming
329
330
```kotlin
331
// Use descriptive scope IDs
332
val userScope = createScope("user-${userId}", named("user"))
333
val requestScope = createScope("request-${requestId}", named("request"))
334
val featureScope = createScope("feature-shopping-${sessionId}", named("shopping"))
335
```
336
337
### 3. Lifecycle Alignment
338
339
```kotlin
340
class ActivityController : KoinScopeComponent {
341
override val scope: Scope = createScope()
342
343
fun onCreate() {
344
// Scope is created, scoped dependencies available
345
}
346
347
fun onDestroy() {
348
scope.close() // Clean up when lifecycle ends
349
}
350
}
351
```