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

module-management.mddocs/

0

# Module Management

1

2

Dynamic module loading and unloading capabilities with integration into Compose lifecycle for automatic cleanup. Enables loading Koin modules on-demand during composition and automatically unloading them when no longer needed.

3

4

## Capabilities

5

6

### rememberKoinModules

7

8

Load and remember Koin modules with automatic lifecycle management tied to Compose's remember system.

9

10

```kotlin { .api }

11

/**

12

* Load and remember Modules & run CompositionKoinModuleLoader to handle scope closure

13

*

14

* @param unloadOnForgotten : unload loaded modules on onForgotten event

15

* @param unloadOnAbandoned : unload loaded modules on onAbandoned event

16

* @param unloadModules : unload loaded modules on onForgotten or onAbandoned event

17

* @param modules : lambda providing list of modules to load

18

*/

19

@Composable

20

@KoinExperimentalAPI

21

inline fun rememberKoinModules(

22

unloadOnForgotten: Boolean? = null,

23

unloadOnAbandoned: Boolean? = null,

24

unloadModules: Boolean = false,

25

crossinline modules: @DisallowComposableCalls () -> List<Module> = { emptyList() }

26

)

27

```

28

29

**Usage Examples:**

30

31

```kotlin

32

import org.koin.compose.module.rememberKoinModules

33

import org.koin.dsl.module

34

35

@Composable

36

fun FeatureScreen(featureEnabled: Boolean) {

37

if (featureEnabled) {

38

// Load feature-specific modules when feature is enabled

39

rememberKoinModules(

40

unloadModules = true // Unload when composition is forgotten/abandoned

41

) {

42

listOf(

43

module {

44

single<FeatureService> { FeatureServiceImpl() }

45

single<FeatureRepository> { FeatureRepositoryImpl() }

46

},

47

module {

48

single<FeatureAnalytics> { FeatureAnalyticsImpl() }

49

}

50

)

51

}

52

53

FeatureContent()

54

} else {

55

DefaultContent()

56

}

57

}

58

59

@Composable

60

fun DynamicModules(userId: String?) {

61

// Load user-specific modules only when user is logged in

62

userId?.let { id ->

63

rememberKoinModules(

64

unloadOnForgotten = true,

65

unloadOnAbandoned = false

66

) {

67

listOf(

68

createUserModule(id),

69

createUserPreferencesModule(id)

70

)

71

}

72

}

73

74

UserInterface()

75

}

76

```

77

78

### Module Lifecycle Control

79

80

Fine-grained control over when modules are unloaded:

81

82

```kotlin

83

@Composable

84

fun ModuleLifecycleDemo() {

85

// Never unload automatically

86

rememberKoinModules {

87

listOf(persistentModule)

88

}

89

90

// Unload only when forgotten (e.g., navigation away)

91

rememberKoinModules(

92

unloadOnForgotten = true,

93

unloadOnAbandoned = false

94

) {

95

listOf(navigationScopedModule)

96

}

97

98

// Unload only when abandoned (e.g., configuration change)

99

rememberKoinModules(

100

unloadOnForgotten = false,

101

unloadOnAbandoned = true

102

) {

103

listOf(configurationSensitiveModule)

104

}

105

106

// Unload in both scenarios (shorthand)

107

rememberKoinModules(unloadModules = true) {

108

listOf(temporaryModule)

109

}

110

}

111

```

112

113

## Advanced Usage Patterns

114

115

### Conditional Module Loading

116

117

```kotlin

118

@Composable

119

fun ConditionalModules(

120

isDebugMode: Boolean,

121

featureFlags: Set<String>,

122

userTier: UserTier

123

) {

124

// Debug modules only in debug mode

125

if (isDebugMode) {

126

rememberKoinModules(unloadModules = true) {

127

listOf(debugModule, loggingModule)

128

}

129

}

130

131

// Feature-specific modules based on flags

132

rememberKoinModules(unloadModules = true) {

133

featureFlags.mapNotNull { flag ->

134

when (flag) {

135

"new_ui" -> newUIModule

136

"analytics" -> analyticsModule

137

"experimental" -> experimentalModule

138

else -> null

139

}

140

}

141

}

142

143

// Tier-based modules

144

rememberKoinModules(unloadModules = true) {

145

when (userTier) {

146

UserTier.FREE -> listOf(freeUserModule)

147

UserTier.PREMIUM -> listOf(freeUserModule, premiumModule)

148

UserTier.ENTERPRISE -> listOf(freeUserModule, premiumModule, enterpriseModule)

149

}

150

}

151

}

152

```

153

154

### Environment-Based Module Loading

155

156

```kotlin

157

@Composable

158

fun EnvironmentModules(environment: Environment) {

159

rememberKoinModules(unloadModules = true) {

160

when (environment) {

161

Environment.DEVELOPMENT -> listOf(

162

devApiModule,

163

mockDataModule,

164

debugToolsModule

165

)

166

Environment.STAGING -> listOf(

167

stagingApiModule,

168

realDataModule,

169

limitedDebugModule

170

)

171

Environment.PRODUCTION -> listOf(

172

prodApiModule,

173

realDataModule,

174

analyticsModule

175

)

176

}

177

}

178

}

179

```

180

181

### Dynamic User Context Modules

182

183

```kotlin

184

@Composable

185

fun UserContextModules(user: User?) {

186

// Base modules always loaded

187

rememberKoinModules {

188

listOf(baseAppModule, authModule)

189

}

190

191

// User-specific modules loaded when user is available

192

user?.let { currentUser ->

193

rememberKoinModules(unloadModules = true) {

194

buildList {

195

// User data module

196

add(createUserDataModule(currentUser.id))

197

198

// Role-based modules

199

if (currentUser.isAdmin) {

200

add(adminModule)

201

}

202

203

if (currentUser.hasPermission("analytics")) {

204

add(userAnalyticsModule)

205

}

206

207

// Locale-specific modules

208

add(createLocaleModule(currentUser.locale))

209

}

210

}

211

}

212

}

213

```

214

215

## Module Creation Helpers

216

217

### Dynamic Module Creation

218

219

```kotlin

220

fun createUserModule(userId: String) = module {

221

single<UserRepository> { UserRepositoryImpl(userId) }

222

single<UserPreferences> { UserPreferencesImpl(userId) }

223

single<UserCache> { UserCacheImpl(userId) }

224

}

225

226

fun createFeatureModule(featureConfig: FeatureConfig) = module {

227

single { featureConfig }

228

single<FeatureService> {

229

if (featureConfig.useV2) {

230

FeatureServiceV2Impl(get())

231

} else {

232

FeatureServiceV1Impl(get())

233

}

234

}

235

}

236

237

fun createEnvironmentModule(env: String) = module {

238

single<ApiClient> {

239

when (env) {

240

"dev" -> DevApiClient()

241

"staging" -> StagingApiClient()

242

"prod" -> ProdApiClient()

243

else -> throw IllegalArgumentException("Unknown environment: $env")

244

}

245

}

246

}

247

```

248

249

### Module Composition

250

251

```kotlin

252

@Composable

253

fun CompositeModules(config: AppConfig) {

254

rememberKoinModules(unloadModules = true) {

255

buildList {

256

// Core modules always included

257

addAll(coreModules)

258

259

// Add platform-specific modules

260

addAll(getPlatformModules())

261

262

// Add feature modules based on config

263

if (config.enableAnalytics) {

264

add(analyticsModule)

265

}

266

267

if (config.enableCrashReporting) {

268

add(crashReportingModule)

269

}

270

271

// Add theme modules

272

add(getThemeModule(config.theme))

273

}

274

}

275

}

276

277

private fun coreModules() = listOf(

278

networkModule,

279

databaseModule,

280

repositoryModule

281

)

282

283

private fun getPlatformModules() = when (Platform.current) {

284

Platform.Android -> listOf(androidModule)

285

Platform.iOS -> listOf(iosModule)

286

Platform.Desktop -> listOf(desktopModule)

287

}

288

```

289

290

## Testing with Module Management

291

292

### Test Module Injection

293

294

```kotlin

295

@Composable

296

fun TestableComponent(isTestMode: Boolean = false) {

297

if (isTestMode) {

298

rememberKoinModules(unloadModules = true) {

299

listOf(

300

testModule,

301

mockModule

302

)

303

}

304

} else {

305

rememberKoinModules(unloadModules = true) {

306

listOf(

307

productionModule,

308

realModule

309

)

310

}

311

}

312

313

ComponentContent()

314

}

315

316

// Test modules

317

val testModule = module {

318

single<ApiService> { MockApiService() }

319

single<Database> { InMemoryDatabase() }

320

}

321

322

val mockModule = module {

323

single<UserRepository> { MockUserRepository() }

324

single<AnalyticsService> { NoOpAnalyticsService() }

325

}

326

```

327

328

### Preview Module Support

329

330

```kotlin

331

@Preview

332

@Composable

333

fun ComponentPreview() {

334

rememberKoinModules {

335

listOf(previewModule)

336

}

337

338

MyComponent()

339

}

340

341

val previewModule = module {

342

single<DataService> { PreviewDataService() }

343

single<ImageLoader> { MockImageLoader() }

344

}

345

```

346

347

## Performance Considerations

348

349

### Module Loading Performance

350

351

```kotlin

352

@Composable

353

fun OptimizedModuleLoading(heavyFeatureEnabled: Boolean) {

354

// Use remember to avoid recreating modules on recomposition

355

val dynamicModules = remember(heavyFeatureEnabled) {

356

if (heavyFeatureEnabled) {

357

listOf(heavyFeatureModule, additionalModule)

358

} else {

359

emptyList()

360

}

361

}

362

363

rememberKoinModules(unloadModules = true) {

364

dynamicModules

365

}

366

}

367

```

368

369

### Lazy Module Creation

370

371

```kotlin

372

@Composable

373

fun LazyModuleLoading() {

374

// Lazy creation of expensive modules

375

rememberKoinModules(unloadModules = true) {

376

listOf(

377

// Only create when accessed

378

module {

379

single<HeavyService> { HeavyServiceImpl() }

380

}

381

)

382

}

383

}

384

```

385

386

## Internal Implementation

387

388

### CompositionKoinModuleLoader

389

390

The internal class that manages module lifecycle:

391

392

```kotlin { .api }

393

@KoinExperimentalAPI

394

@KoinInternalApi

395

class CompositionKoinModuleLoader(

396

val modules: List<Module>,

397

val koin: Koin,

398

val unloadOnForgotten: Boolean,

399

val unloadOnAbandoned: Boolean

400

) : RememberObserver {

401

402

init {

403

koin.loadModules(modules)

404

}

405

406

override fun onRemembered() {

407

// Module loading happens in init

408

}

409

410

override fun onForgotten() {

411

if (unloadOnForgotten) {

412

unloadModules()

413

}

414

}

415

416

override fun onAbandoned() {

417

if (unloadOnAbandoned) {

418

unloadModules()

419

}

420

}

421

422

private fun unloadModules() {

423

koin.unloadModules(modules)

424

}

425

}

426

```

427

428

## Core Types

429

430

```kotlin { .api }

431

// Module types

432

interface Module {

433

val id: String

434

val createdAtStart: Boolean

435

}

436

437

// Module lifecycle

438

interface RememberObserver {

439

fun onRemembered()

440

fun onForgotten()

441

fun onAbandoned()

442

}

443

444

// Koin instance for module management

445

interface Koin {

446

fun loadModules(modules: List<Module>)

447

fun unloadModules(modules: List<Module>)

448

}

449

```

450

451

## Error Handling

452

453

### Module Loading Failures

454

455

```kotlin

456

@Composable

457

fun SafeModuleLoading() {

458

try {

459

rememberKoinModules(unloadModules = true) {

460

listOf(

461

riskyModule,

462

dependentModule

463

)

464

}

465

466

ModuleContent()

467

} catch (e: ModuleCreationException) {

468

Text("Failed to load modules: ${e.message}")

469

}

470

}

471

```

472

473

### Circular Dependencies

474

475

```kotlin

476

// Avoid circular dependencies in dynamic modules

477

val moduleA = module {

478

single<ServiceA> { ServiceAImpl(get<ServiceB>()) }

479

}

480

481

val moduleB = module {

482

single<ServiceB> { ServiceBImpl(get<ServiceA>()) } // ❌ Circular dependency

483

}

484

485

// Better approach: Use interfaces or break the cycle

486

val moduleA = module {

487

single<ServiceA> { ServiceAImpl(get<ServiceBInterface>()) }

488

}

489

490

val moduleB = module {

491

single<ServiceBInterface> { ServiceBImpl() }

492

}

493

```

494

495

## Best Practices

496

497

### Module Organization

498

499

```kotlin

500

// ✅ Good: Organize modules by feature/layer

501

val networkModule = module { /* network dependencies */ }

502

val dataModule = module { /* data layer dependencies */ }

503

val userFeatureModule = module { /* user feature dependencies */ }

504

505

// ❌ Poor: Monolithic modules

506

val everythingModule = module {

507

// Too many unrelated dependencies

508

}

509

```

510

511

### Lifecycle Management

512

513

```kotlin

514

// ✅ Good: Match module lifecycle to business logic

515

@Composable

516

fun UserSession() {

517

// Load user modules for entire session

518

rememberKoinModules(unloadOnForgotten = true) {

519

listOf(userSessionModule)

520

}

521

}

522

523

// ✅ Good: Temporary modules for short-lived features

524

@Composable

525

fun OnboardingFlow() {

526

rememberKoinModules(unloadModules = true) {

527

listOf(onboardingModule) // Unload when onboarding ends

528

}

529

}

530

```