0
# Scope Management
1
2
Experimental APIs for creating and managing Koin scopes with automatic lifecycle management tied to Compose recomposition, enabling fine-grained dependency scoping within Compose hierarchies.
3
4
## Capabilities
5
6
### KoinScope with Definition
7
8
Create Koin Scope using a lambda definition and automatically close it when the Composition is forgotten or abandoned.
9
10
```kotlin { .api }
11
/**
12
* Create Koin Scope and close it when Composition is forgotten/abandoned
13
* @param scopeDefinition Lambda to define scope
14
* @param content Composable content
15
*/
16
@KoinExperimentalAPI
17
@Composable
18
fun KoinScope(
19
scopeDefinition: Koin.() -> Scope,
20
content: @Composable () -> Unit
21
)
22
```
23
24
**Usage Examples:**
25
26
```kotlin
27
@Composable
28
fun FeatureWithCustomScope() {
29
KoinScope(
30
scopeDefinition = {
31
createScope("feature-scope", named("feature"))
32
}
33
) {
34
// Content has access to feature-scoped dependencies
35
FeatureContent()
36
}
37
}
38
39
@Composable
40
fun DynamicScope(userId: String) {
41
KoinScope(
42
scopeDefinition = {
43
createScope("user-$userId", named("user")) {
44
// Scope parameters can be provided
45
parametersOf(userId)
46
}
47
}
48
) {
49
UserProfile(userId)
50
}
51
}
52
```
53
54
### Typed KoinScope with ScopeID
55
56
Create typed Koin Scope with automatic lifecycle management using a scope identifier.
57
58
```kotlin { .api }
59
/**
60
* Create typed Koin Scope with automatic lifecycle management
61
* @param T Scope type
62
* @param scopeID Scope identifier
63
* @param content Composable content
64
*/
65
@KoinExperimentalAPI
66
@Composable
67
inline fun <reified T : Any> KoinScope(
68
scopeID: ScopeID,
69
noinline content: @Composable () -> Unit
70
)
71
```
72
73
**Usage Examples:**
74
75
```kotlin
76
// Define scope type
77
class UserSessionScope
78
79
@Composable
80
fun UserSession(sessionId: String) {
81
KoinScope<UserSessionScope>(scopeID = sessionId) {
82
// Content within user session scope
83
SessionContent()
84
}
85
}
86
87
@Composable
88
fun TypedFeatureScope() {
89
KoinScope<FeatureScope>(scopeID = "main-feature") {
90
FeatureComponents()
91
}
92
}
93
```
94
95
### KoinScope with Qualifier
96
97
Create Koin Scope with a qualifier and automatic lifecycle management.
98
99
```kotlin { .api }
100
/**
101
* Create Koin Scope with qualifier and automatic lifecycle management
102
* @param scopeID Scope identifier
103
* @param scopeQualifier Scope qualifier
104
* @param content Composable content
105
*/
106
@KoinExperimentalAPI
107
@Composable
108
fun KoinScope(
109
scopeID: ScopeID,
110
scopeQualifier: Qualifier,
111
content: @Composable () -> Unit
112
)
113
```
114
115
**Usage Examples:**
116
117
```kotlin
118
@Composable
119
fun QualifiedScope(featureId: String) {
120
KoinScope(
121
scopeID = featureId,
122
scopeQualifier = named("feature-scope")
123
) {
124
// Content with qualified scope access
125
QualifiedFeatureContent()
126
}
127
}
128
129
@Composable
130
fun MultiLevelScope() {
131
KoinScope(
132
scopeID = "level1",
133
scopeQualifier = named("primary")
134
) {
135
KoinScope(
136
scopeID = "level2",
137
scopeQualifier = named("secondary")
138
) {
139
NestedScopeContent()
140
}
141
}
142
}
143
```
144
145
### Remember Koin Scope
146
147
Remember Koin Scope with automatic closure handling when the composable is disposed.
148
149
```kotlin { .api }
150
/**
151
* Remember Koin Scope with automatic closure handling
152
* @param scope Koin scope to remember
153
* @return The same scope with lifecycle management
154
*/
155
@KoinExperimentalAPI
156
@Composable
157
fun rememberKoinScope(scope: Scope): Scope
158
```
159
160
**Usage Examples:**
161
162
```kotlin
163
@Composable
164
fun RememberedScope() {
165
val koin = getKoin()
166
val customScope = rememberKoinScope(
167
koin.createScope("custom", named("feature"))
168
)
169
170
// Use the remembered scope
171
val scopedService: ScopedService = koinInject(scope = customScope)
172
173
// Scope will be automatically closed when component is disposed
174
}
175
176
@Composable
177
fun ConditionalScope(condition: Boolean) {
178
val koin = getKoin()
179
180
if (condition) {
181
val conditionalScope = rememberKoinScope(
182
koin.createScope("conditional", named("temp"))
183
)
184
185
ConditionalContent(scope = conditionalScope)
186
}
187
}
188
```
189
190
## Lifecycle Management
191
192
### Automatic Cleanup
193
194
All scope management functions automatically handle scope lifecycle:
195
196
```kotlin
197
@Composable
198
fun LifecycleExample() {
199
// Scope created when composable enters composition
200
KoinScope(
201
scopeDefinition = { createScope("auto-cleanup", named("temp")) }
202
) {
203
// Scope available here
204
205
LaunchedEffect(Unit) {
206
println("Scope created and available")
207
}
208
209
DisposableEffect(Unit) {
210
onDispose {
211
// Scope automatically closed here
212
println("Scope will be closed")
213
}
214
}
215
216
ScopedContent()
217
}
218
// Scope closed when composable leaves composition
219
}
220
```
221
222
### Manual Scope Control
223
224
For advanced use cases, combine with manual scope management:
225
226
```kotlin
227
@Composable
228
fun ManualScopeControl() {
229
val koin = getKoin()
230
var manualScope by remember { mutableStateOf<Scope?>(null) }
231
232
// Create scope manually
233
Button(
234
onClick = {
235
manualScope = koin.createScope("manual", named("controlled"))
236
}
237
) {
238
Text("Create Scope")
239
}
240
241
// Use remembered scope when available
242
manualScope?.let { scope ->
243
val rememberedScope = rememberKoinScope(scope)
244
245
ScopedContent(scope = rememberedScope)
246
247
Button(
248
onClick = {
249
scope.close()
250
manualScope = null
251
}
252
) {
253
Text("Close Scope")
254
}
255
}
256
}
257
```
258
259
## Scope Hierarchies
260
261
### Nested Scopes
262
263
Create hierarchical scope structures:
264
265
```kotlin
266
@Composable
267
fun NestedScopes() {
268
KoinScope(
269
scopeID = "app-feature",
270
scopeQualifier = named("feature")
271
) {
272
// Parent scope content
273
ParentScopeContent()
274
275
KoinScope(
276
scopeID = "sub-feature",
277
scopeQualifier = named("sub-feature")
278
) {
279
// Child scope content with access to parent scope
280
ChildScopeContent()
281
}
282
}
283
}
284
```
285
286
### Scope Communication
287
288
Share data between scopes:
289
290
```kotlin
291
@Composable
292
fun ScopeCommunication() {
293
KoinScope(
294
scopeDefinition = {
295
createScope("publisher", named("data-source"))
296
}
297
) {
298
val publisher: DataPublisher = koinInject()
299
300
KoinScope(
301
scopeDefinition = {
302
createScope("subscriber", named("data-consumer"))
303
}
304
) {
305
val subscriber: DataSubscriber = koinInject()
306
307
LaunchedEffect(publisher, subscriber) {
308
publisher.dataFlow.collect { data ->
309
subscriber.process(data)
310
}
311
}
312
313
ConsumerContent()
314
}
315
}
316
}
317
```
318
319
## Integration with State
320
321
### Scope-Based State
322
323
Create state that's tied to scope lifecycle:
324
325
```kotlin
326
@Composable
327
fun ScopeBasedState() {
328
KoinScope(
329
scopeID = "stateful",
330
scopeQualifier = named("state-scope")
331
) {
332
val stateManager: StateManager = koinInject()
333
var state by remember { mutableStateOf(stateManager.initialState) }
334
335
LaunchedEffect(stateManager) {
336
stateManager.stateFlow.collect { newState ->
337
state = newState
338
}
339
}
340
341
StatefulContent(
342
state = state,
343
onStateChange = stateManager::updateState
344
)
345
}
346
}
347
```
348
349
### Reactive Scope Updates
350
351
React to scope changes:
352
353
```kotlin
354
@Composable
355
fun ReactiveScopeUpdates(scopeConfig: ScopeConfig) {
356
KoinScope(
357
scopeDefinition = {
358
createScope(scopeConfig.id, scopeConfig.qualifier)
359
}
360
) {
361
val currentScope = currentKoinScope()
362
363
LaunchedEffect(currentScope.id) {
364
println("Scope changed to: ${currentScope.id}")
365
}
366
367
ScopeAwareContent(scopeId = currentScope.id)
368
}
369
}
370
```
371
372
## Error Handling
373
374
### Scope Creation Errors
375
376
Handle scope creation and lifecycle errors:
377
378
```kotlin
379
@Composable
380
fun SafeScopeCreation() {
381
var scopeError by remember { mutableStateOf<String?>(null) }
382
383
scopeError?.let { error ->
384
ErrorDisplay(error) {
385
scopeError = null
386
}
387
}
388
389
try {
390
KoinScope(
391
scopeDefinition = {
392
// Scope creation might fail
393
createScope("risky-scope", named("risky"))
394
}
395
) {
396
SafeScopeContent()
397
}
398
} catch (e: Exception) {
399
LaunchedEffect(e) {
400
scopeError = "Scope creation failed: ${e.message}"
401
}
402
}
403
}
404
```
405
406
### Scope Dependency Errors
407
408
Handle missing scoped dependencies:
409
410
```kotlin
411
@Composable
412
fun SafeScopedInjection() {
413
KoinScope(
414
scopeID = "feature",
415
scopeQualifier = named("feature-scope")
416
) {
417
try {
418
val service: ScopedService = koinInject()
419
ServiceContent(service)
420
} catch (e: NoBeanDefFoundException) {
421
MissingDependencyFallback()
422
}
423
}
424
}
425
```
426
427
## Performance Considerations
428
429
### Scope Reuse
430
431
Reuse scopes when possible to avoid creation overhead:
432
433
```kotlin
434
@Composable
435
fun EfficientScopeUsage(featureId: String) {
436
// Scope recreated only when featureId changes
437
KoinScope(
438
scopeDefinition = {
439
createScope("feature-$featureId", named("feature"))
440
}
441
) {
442
FeatureContent(featureId)
443
}
444
}
445
```
446
447
### Conditional Scoping
448
449
Create scopes only when needed:
450
451
```kotlin
452
@Composable
453
fun ConditionalScopeCreation(needsScope: Boolean) {
454
if (needsScope) {
455
KoinScope(
456
scopeID = "conditional",
457
scopeQualifier = named("when-needed")
458
) {
459
ScopedContent()
460
}
461
} else {
462
UnscopedContent()
463
}
464
}
465
```
466
467
## Best Practices
468
469
1. **Lifecycle Awareness**: Trust automatic cleanup - scopes are closed when composables are disposed
470
2. **Scope Naming**: Use descriptive scope IDs and qualifiers for debugging
471
3. **Hierarchy Design**: Design scope hierarchies to match your component structure
472
4. **Error Handling**: Implement proper error handling for scope creation and dependency resolution
473
5. **Performance**: Reuse scopes when possible and create them conditionally
474
6. **State Integration**: Leverage scope lifecycle for component-specific state management
475
7. **Experimental API**: Remember these are experimental APIs and may change in future versions