or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-setup.mdcontext-access.mddependency-injection.mdindex.mdmodule-management.mdscope-management.md

scope-management.mddocs/

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