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

Type-safe dependency resolution functions that integrate seamlessly with Compose recomposition, supporting parameters, qualifiers, and custom scopes for flexible dependency injection patterns.

3

4

## Capabilities

5

6

### Basic Dependency Injection

7

8

Resolve Koin dependency without parameters using reified generics for type safety.

9

10

```kotlin { .api }

11

/**

12

* Resolve Koin dependency without parameters

13

* @param qualifier Dependency qualifier (optional)

14

* @param scope Koin scope (default: current scope)

15

* @return Instance of type T

16

*/

17

@Composable

18

inline fun <reified T> koinInject(

19

qualifier: Qualifier? = null,

20

scope: Scope = currentKoinScope()

21

): T

22

```

23

24

**Usage Examples:**

25

26

```kotlin

27

@Composable

28

fun UserScreen() {

29

// Basic injection

30

val repository: UserRepository = koinInject()

31

val apiService: ApiService = koinInject()

32

33

// With qualifier

34

val cacheRepo: UserRepository = koinInject(qualifier = named("cache"))

35

val networkRepo: UserRepository = koinInject(qualifier = named("network"))

36

37

// With custom scope

38

val sessionService: SessionService = koinInject(scope = getKoin().getScope("session"))

39

40

LaunchedEffect(Unit) {

41

val users = repository.getAllUsers()

42

// Use injected dependencies

43

}

44

}

45

```

46

47

### Dependency Injection with Parameters (Lambda)

48

49

Resolve Koin dependency with parameters using a lambda function. Note that parameters are unwrapped on recomposition, which may impact performance.

50

51

```kotlin { .api }

52

/**

53

* Resolve Koin dependency with parameters (unwraps to ParametersHolder on recomposition)

54

* @param qualifier Dependency qualifier (optional)

55

* @param scope Koin scope (default: current scope)

56

* @param parameters Injected parameters with lambda

57

* @return Instance of type T

58

* @note Parameters unwrapped on recomposition - use ParametersHolder version for better performance

59

*/

60

@Composable

61

inline fun <reified T> koinInject(

62

qualifier: Qualifier? = null,

63

scope: Scope = currentKoinScope(),

64

noinline parameters: ParametersDefinition

65

): T

66

```

67

68

**Usage Examples:**

69

70

```kotlin

71

@Composable

72

fun DetailScreen(userId: String) {

73

// Inject with parameters - unwrapped on each recomposition

74

val userService: UserService = koinInject { parametersOf(userId) }

75

val userProfile: UserProfile = koinInject(

76

qualifier = named("detailed")

77

) { parametersOf(userId, true) }

78

79

// Use the injected services

80

LaunchedEffect(userId) {

81

val user = userService.getUser()

82

// ...

83

}

84

}

85

```

86

87

### Dependency Injection with ParametersHolder

88

89

Resolve Koin dependency with ParametersHolder for better performance by avoiding parameter unwrapping on recomposition.

90

91

```kotlin { .api }

92

/**

93

* Resolve Koin dependency with ParametersHolder (better performance)

94

* @param qualifier Dependency qualifier (optional)

95

* @param scope Koin scope (default: current scope)

96

* @param parametersHolder Parameters (use parametersOf(), no lambda)

97

* @return Instance of type T

98

*/

99

@Composable

100

inline fun <reified T> koinInject(

101

qualifier: Qualifier? = null,

102

scope: Scope = currentKoinScope(),

103

parametersHolder: ParametersHolder

104

): T

105

```

106

107

**Usage Examples:**

108

109

```kotlin

110

@Composable

111

fun OptimizedDetailScreen(userId: String) {

112

// Better performance - parameters not unwrapped on recomposition

113

val userParams = remember(userId) { parametersOf(userId) }

114

val userService: UserService = koinInject(parametersHolder = userParams)

115

116

val detailedParams = remember(userId) { parametersOf(userId, true) }

117

val userProfile: UserProfile = koinInject(

118

qualifier = named("detailed"),

119

parametersHolder = detailedParams

120

)

121

122

// Use the injected services

123

}

124

```

125

126

## Performance Considerations

127

128

### Parameter Handling

129

130

When injecting dependencies with parameters, choose the appropriate method based on performance requirements:

131

132

- **Lambda parameters**: Convenient but unwrapped on every recomposition

133

- **ParametersHolder**: Better performance, especially for frequently recomposing components

134

135

```kotlin

136

@Composable

137

fun PerformanceExample(id: String) {

138

// ❌ Poor performance - unwrapped on every recomposition

139

val service1: MyService = koinInject { parametersOf(id) }

140

141

// ✅ Better performance - parameters remembered

142

val params = remember(id) { parametersOf(id) }

143

val service2: MyService = koinInject(parametersHolder = params)

144

}

145

```

146

147

### Scope Management

148

149

Inject from appropriate scopes to optimize memory usage and lifecycle management:

150

151

```kotlin

152

@Composable

153

fun ScopeExample() {

154

// Application-level singleton

155

val appService: AppService = koinInject()

156

157

// Session-scoped instance

158

val sessionScope = getKoin().getScope("session")

159

val sessionService: SessionService = koinInject(scope = sessionScope)

160

161

// Feature-scoped instance

162

val featureScope = getKoin().getScope("feature")

163

val featureService: FeatureService = koinInject(scope = featureScope)

164

}

165

```

166

167

## Type Safety and Generics

168

169

The injection functions use reified generics to maintain full type safety:

170

171

```kotlin

172

@Composable

173

fun TypeSafetyExample() {

174

// Type inferred automatically

175

val stringRepo: Repository<String> = koinInject()

176

val userRepo: Repository<User> = koinInject()

177

178

// With qualifiers for different implementations

179

val cacheRepo: Repository<User> = koinInject(qualifier = named("cache"))

180

val dbRepo: Repository<User> = koinInject(qualifier = named("database"))

181

}

182

```

183

184

## Error Handling

185

186

Dependency injection functions will throw exceptions if dependencies cannot be resolved:

187

188

- `NoBeanDefFoundException`: When the requested dependency is not defined

189

- `BeanCreationException`: When there's an error creating the bean instance

190

- `UnknownKoinContext`: When Koin context is not properly initialized

191

192

```kotlin

193

@Composable

194

fun SafeInjection() {

195

try {

196

val service: MyService = koinInject()

197

// Use service

198

} catch (e: NoBeanDefFoundException) {

199

// Handle missing dependency

200

} catch (e: BeanCreationException) {

201

// Handle creation error

202

}

203

}

204

```

205

206

## Integration with Compose

207

208

### State and Effects

209

210

Injected dependencies work seamlessly with Compose state and effects:

211

212

```kotlin

213

@Composable

214

fun IntegrationExample() {

215

val repository: DataRepository = koinInject()

216

var data by remember { mutableStateOf<List<Data>?>(null) }

217

var loading by remember { mutableStateOf(false) }

218

219

LaunchedEffect(repository) {

220

loading = true

221

try {

222

data = repository.loadData()

223

} finally {

224

loading = false

225

}

226

}

227

228

// UI based on injected data

229

if (loading) {

230

CircularProgressIndicator()

231

} else {

232

LazyColumn {

233

items(data.orEmpty()) { item ->

234

DataItem(item)

235

}

236

}

237

}

238

}

239

```

240

241

### ViewModels and State Holders

242

243

Inject ViewModels and other state holders for MVVM patterns:

244

245

```kotlin

246

@Composable

247

fun ViewModelExample() {

248

val viewModel: UserViewModel = koinInject()

249

val uiState by viewModel.uiState.collectAsState()

250

251

LaunchedEffect(Unit) {

252

viewModel.loadUsers()

253

}

254

255

UserList(

256

users = uiState.users,

257

onUserClick = viewModel::selectUser

258

)

259

}

260

```

261

262

## Best Practices

263

264

1. **Use ParametersHolder for Performance**: When injecting with parameters in frequently recomposing components

265

2. **Remember Parameters**: Always wrap `parametersOf()` calls in `remember` with appropriate keys

266

3. **Scope Appropriately**: Inject from the most appropriate scope for your use case

267

4. **Handle Errors**: Implement proper error handling for dependency resolution failures

268

5. **Type Safety**: Leverage reified generics for compile-time type checking

269

6. **Qualifier Naming**: Use descriptive qualifiers to distinguish between different implementations