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

dependency-injection.mddocs/

0

# Dependency Injection

1

2

Functions for injecting dependencies into Composable functions with type safety and performance optimization through Compose's remember system. The koinInject function provides three overloads to handle different parameter scenarios.

3

4

## Capabilities

5

6

### Basic Dependency Injection

7

8

Resolve Koin dependency for a given type without parameters.

9

10

```kotlin { .api }

11

/**

12

* Resolve Koin dependency for given Type T

13

*

14

* @param qualifier - dependency qualifier

15

* @param scope - Koin's root by default

16

* @return instance of type T

17

*/

18

@Composable

19

inline fun <reified T> koinInject(

20

qualifier: Qualifier? = null,

21

scope: Scope = currentKoinScope()

22

): T

23

```

24

25

**Usage Examples:**

26

27

```kotlin

28

import org.koin.compose.koinInject

29

30

@Composable

31

fun UserScreen() {

32

// Basic injection

33

val userRepository: UserRepository = koinInject()

34

35

// With qualifier

36

val apiClient: ApiClient = koinInject(qualifier = named("public"))

37

38

// With specific scope

39

val sessionService: SessionService = koinInject(scope = someSpecificScope)

40

41

// Use the injected dependencies

42

LaunchedEffect(Unit) {

43

val users = userRepository.getUsers()

44

// Handle users...

45

}

46

}

47

```

48

49

### Parameterized Dependency Injection with Lambda

50

51

Resolve Koin dependency with parameters provided via lambda. Note: This version unwraps parameters to ParametersHolder and will be triggered on recomposition.

52

53

```kotlin { .api }

54

/**

55

* Resolve Koin dependency for given Type T

56

*

57

* Note: this version unwrap parameters to ParametersHolder in order to let remember all parameters

58

* This parameters unwrap will be triggered on recomposition

59

*

60

* For better performances we advise to use koinInject(Qualifier,Scope,ParametersHolder)

61

*

62

* @param qualifier - dependency qualifier

63

* @param scope - Koin's root by default

64

* @param parameters - injected parameters (with lambda & parametersOf())

65

* @return instance of type T

66

*/

67

@Composable

68

inline fun <reified T> koinInject(

69

qualifier: Qualifier? = null,

70

scope: Scope = currentKoinScope(),

71

noinline parameters: ParametersDefinition

72

): T

73

```

74

75

**Usage Examples:**

76

77

```kotlin

78

import org.koin.compose.koinInject

79

import org.koin.core.parameter.parametersOf

80

81

@Composable

82

fun UserDetailScreen(userId: String) {

83

// Inject with parameters using lambda

84

val userService: UserService = koinInject {

85

parametersOf(userId, "detailed")

86

}

87

88

// More complex parameters

89

val analyticsService: AnalyticsService = koinInject(

90

qualifier = named("user_analytics")

91

) {

92

parametersOf(userId, System.currentTimeMillis())

93

}

94

95

// Use the services

96

LaunchedEffect(userId) {

97

val user = userService.getUser()

98

analyticsService.trackUserView(user)

99

}

100

}

101

```

102

103

### Parameterized Dependency Injection with ParametersHolder

104

105

Resolve Koin dependency with pre-created parameters. This approach provides better performance as parameters are not unwrapped on each recomposition.

106

107

```kotlin { .api }

108

/**

109

* Resolve Koin dependency for given Type T

110

*

111

* @param qualifier - dependency qualifier

112

* @param scope - Koin's root by default

113

* @param parametersHolder - parameters (used with parametersOf(), no lambda)

114

* @return instance of type T

115

*/

116

@Composable

117

inline fun <reified T> koinInject(

118

qualifier: Qualifier? = null,

119

scope: Scope = currentKoinScope(),

120

parametersHolder: ParametersHolder

121

): T

122

```

123

124

**Usage Examples:**

125

126

```kotlin

127

import org.koin.compose.koinInject

128

import org.koin.core.parameter.parametersOf

129

import androidx.compose.runtime.remember

130

131

@Composable

132

fun UserDetailScreen(userId: String) {

133

// Create parameters holder once

134

val userParams = remember(userId) {

135

parametersOf(userId, "detailed")

136

}

137

138

// Inject with parameters holder (better performance)

139

val userService: UserService = koinInject(

140

parametersHolder = userParams

141

)

142

143

// Multiple services with same parameters

144

val userCache: UserCache = koinInject(

145

qualifier = named("memory_cache"),

146

parametersHolder = userParams

147

)

148

149

// Use the services

150

LaunchedEffect(userId) {

151

val user = userService.getUser()

152

userCache.store(user)

153

}

154

}

155

```

156

157

## Performance Considerations

158

159

### Remember Integration

160

161

All koinInject functions use Compose's `remember` internally for performance optimization:

162

163

```kotlin

164

// Internal implementation uses remember for caching

165

return remember(qualifier, scope) {

166

scope.get(T::class, qualifier)

167

}

168

169

// With parameters, both qualifier, scope, and parameters are remembered

170

return remember(qualifier, scope, parametersHolder) {

171

scope.getWithParameters(T::class, qualifier, parametersHolder)

172

}

173

```

174

175

### Parameter Performance

176

177

For best performance with parameters:

178

179

1. **Use ParametersHolder version** when possible (third overload)

180

2. **Remember parameter creation** when using lambda version

181

3. **Avoid recreating parameters** on every recomposition

182

183

```kotlin

184

// ❌ Poor performance - parameters recreated on every recomposition

185

val service: Service = koinInject { parametersOf(userId, timestamp) }

186

187

// ✅ Better performance - parameters remembered

188

val params = remember(userId) { parametersOf(userId, timestamp) }

189

val service: Service = koinInject(parametersHolder = params)

190

```

191

192

## Qualifier Usage

193

194

### Named Qualifiers

195

196

```kotlin

197

import org.koin.core.qualifier.named

198

199

@Composable

200

fun ApiScreen() {

201

val publicApi: ApiClient = koinInject(qualifier = named("public"))

202

val adminApi: ApiClient = koinInject(qualifier = named("admin"))

203

val internalApi: ApiClient = koinInject(qualifier = named("internal"))

204

}

205

```

206

207

### String Qualifiers

208

209

```kotlin

210

import org.koin.core.qualifier.StringQualifier

211

212

@Composable

213

fun DatabaseScreen() {

214

val readOnlyDb = koinInject<Database>(qualifier = StringQualifier("readonly"))

215

val writeDb = koinInject<Database>(qualifier = StringQualifier("write"))

216

}

217

```

218

219

## Scope Usage

220

221

### Default Scope

222

223

By default, `koinInject` uses the current composition's scope:

224

225

```kotlin

226

@Composable

227

fun MyScreen() {

228

// Uses currentKoinScope() by default

229

val service: MyService = koinInject()

230

}

231

```

232

233

### Custom Scope

234

235

```kotlin

236

@Composable

237

fun ScopedComponent() {

238

val customScope = remember { getKoin().createScope<MyScope>("custom_id") }

239

240

val scopedService: ScopedService = koinInject(scope = customScope)

241

242

DisposableEffect(customScope) {

243

onDispose {

244

customScope.close()

245

}

246

}

247

}

248

```

249

250

## Dependency Types

251

252

```kotlin { .api }

253

// Core parameter types

254

class ParametersHolder

255

typealias ParametersDefinition = () -> ParametersHolder

256

257

// Qualifier types

258

interface Qualifier

259

class StringQualifier(val value: String) : Qualifier

260

fun named(name: String): Qualifier

261

262

// Scope types

263

interface Scope {

264

fun <T : Any> get(clazz: KClass<T>, qualifier: Qualifier?): T

265

fun <T : Any> getWithParameters(clazz: KClass<T>, qualifier: Qualifier?, parameters: ParametersHolder): T

266

}

267

```

268

269

## Error Handling

270

271

Common injection errors:

272

273

- **NoBeanDefFoundException**: When requested dependency is not defined in Koin modules

274

- **ClosedScopeException**: When trying to inject from a closed scope

275

- **UnknownKoinContext**: When Koin context is not available in composition

276

- **ParameterException**: When required parameters are missing or incorrect

277

278

```kotlin

279

@Composable

280

fun SafeInjection() {

281

try {

282

val service: MyService = koinInject()

283

// Use service

284

} catch (e: Exception) {

285

// Handle injection failure

286

Text("Service unavailable: ${e.message}")

287

}

288

}

289

```