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