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
```