android-sdd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/index.js +143 -0
  2. package/package.json +27 -0
  3. package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
  4. package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
  5. package/skills/Android Platform/Configuration/SKILL.md +201 -0
  6. package/skills/Android Platform/Filesystem/SKILL.md +216 -0
  7. package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
  8. package/skills/Android Platform/Manifest/SKILL.md +226 -0
  9. package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
  10. package/skills/Android Platform/Resources/SKILL.md +234 -0
  11. package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
  12. package/skills/Android Platform/State Restoration/SKILL.md +210 -0
  13. package/skills/Architecture/Bounded Context/SKILL.md +207 -0
  14. package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
  15. package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
  16. package/skills/Architecture/Entity Design/SKILL.md +243 -0
  17. package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
  18. package/skills/Architecture/MVI/SKILL.md +224 -0
  19. package/skills/Architecture/MVVM/SKILL.md +198 -0
  20. package/skills/Architecture/Modularization/SKILL.md +194 -0
  21. package/skills/Architecture/Offline First/SKILL.md +249 -0
  22. package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
  23. package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
  24. package/skills/Architecture/State Management/SKILL.md +229 -0
  25. package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
  26. package/skills/Architecture/Use Case Design/SKILL.md +244 -0
  27. package/skills/Architecture/Value Object/SKILL.md +226 -0
  28. package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
  29. package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
  30. package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
  31. package/skills/Build System/Build Cache/SKILL.md +233 -0
  32. package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
  33. package/skills/Build System/Build Variant/SKILL.md +215 -0
  34. package/skills/Build System/Convention Plugin/SKILL.md +288 -0
  35. package/skills/Build System/Dependency Management/SKILL.md +261 -0
  36. package/skills/Build System/Gradle/SKILL.md +284 -0
  37. package/skills/Build System/Incremental Build/SKILL.md +199 -0
  38. package/skills/Build System/KAPT/SKILL.md +198 -0
  39. package/skills/Build System/KSP/SKILL.md +263 -0
  40. package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
  41. package/skills/Build System/Specialized/C++/SKILL.md +308 -0
  42. package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
  43. package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
  44. package/skills/Build System/Version Catalog/SKILL.md +304 -0
  45. package/skills/Concurrency/Background Processing/SKILL.md +185 -0
  46. package/skills/Concurrency/Channel/SKILL.md +207 -0
  47. package/skills/Concurrency/Coroutine/SKILL.md +200 -0
  48. package/skills/Concurrency/Flow/SKILL.md +179 -0
  49. package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
  50. package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
  51. package/skills/Concurrency/StateFlow/SKILL.md +175 -0
  52. package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
  53. package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
  54. package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
  55. package/skills/Core Language/DSL/SKILL.md +186 -0
  56. package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
  57. package/skills/Core Language/Immutability/SKILL.md +156 -0
  58. package/skills/Core Language/KMP/SKILL.md +182 -0
  59. package/skills/Core Language/Kotlin/SKILL.md +187 -0
  60. package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
  61. package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
  62. package/skills/Core Language/Serialization/SKILL.md +191 -0
  63. package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
  64. package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
  65. package/skills/Data Layer/DAO/SKILL.md +225 -0
  66. package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
  67. package/skills/Data Layer/DataStore/SKILL.md +264 -0
  68. package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
  69. package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
  70. package/skills/Data Layer/File Storage/SKILL.md +247 -0
  71. package/skills/Data Layer/Indexing/SKILL.md +184 -0
  72. package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
  73. package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
  74. package/skills/Data Layer/Migration/SKILL.md +243 -0
  75. package/skills/Data Layer/Paging/SKILL.md +264 -0
  76. package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
  77. package/skills/Data Layer/Room/SKILL.md +244 -0
  78. package/skills/Data Layer/SQLite/SKILL.md +255 -0
  79. package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
  80. package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
  81. package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
  82. package/skills/Dependency Injection/Koin/SKILL.md +282 -0
  83. package/skills/Developer Experience/Detekt/SKILL.md +272 -0
  84. package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
  85. package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
  86. package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
  87. package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
  88. package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
  89. package/skills/Media/Audio/SKILL.md +257 -0
  90. package/skills/Media/Camera/SKILL.md +229 -0
  91. package/skills/Media/CameraX/SKILL.md +295 -0
  92. package/skills/Media/ExoPlayer/SKILL.md +258 -0
  93. package/skills/Media/Video/SKILL.md +228 -0
  94. package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
  95. package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
  96. package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
  97. package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
  98. package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
  99. package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
  100. package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
  101. package/skills/Navigation/Navigation/SKILL.md +215 -0
  102. package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
  103. package/skills/Networking/API Contract/SKILL.md +220 -0
  104. package/skills/Networking/Authentication/SKILL.md +210 -0
  105. package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
  106. package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
  107. package/skills/Networking/Ktor/SKILL.md +219 -0
  108. package/skills/Networking/Multipart Upload/SKILL.md +213 -0
  109. package/skills/Networking/OkHttp/SKILL.md +193 -0
  110. package/skills/Networking/REST/SKILL.md +178 -0
  111. package/skills/Networking/Rate Limiting/SKILL.md +170 -0
  112. package/skills/Networking/Retrofit/SKILL.md +241 -0
  113. package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
  114. package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
  115. package/skills/Networking/WebSocket/SKILL.md +224 -0
  116. package/skills/Observability/Crash Reporting/SKILL.md +219 -0
  117. package/skills/Observability/Logging/SKILL.md +168 -0
  118. package/skills/Observability/Metrics/SKILL.md +227 -0
  119. package/skills/Observability/Structured Logging/SKILL.md +234 -0
  120. package/skills/Performance/ANR Prevention/SKILL.md +192 -0
  121. package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
  122. package/skills/Performance/App Startup/SKILL.md +183 -0
  123. package/skills/Performance/Baseline Profile/SKILL.md +205 -0
  124. package/skills/Performance/Battery Optimization/SKILL.md +192 -0
  125. package/skills/Performance/Benchmark/SKILL.md +182 -0
  126. package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
  127. package/skills/Performance/Compose Optimization/SKILL.md +187 -0
  128. package/skills/Performance/Heap Management/SKILL.md +184 -0
  129. package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
  130. package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
  131. package/skills/Performance/Rendering Performance/SKILL.md +205 -0
  132. package/skills/Performance/Startup Optimization/SKILL.md +219 -0
  133. package/skills/Security/Biometric/SKILL.md +224 -0
  134. package/skills/Security/Certificate Transparency/SKILL.md +158 -0
  135. package/skills/Security/Cryptography/SKILL.md +244 -0
  136. package/skills/Security/Encrypted Storage/SKILL.md +273 -0
  137. package/skills/Security/Frida Detection/SKILL.md +230 -0
  138. package/skills/Security/Hook Detection/SKILL.md +197 -0
  139. package/skills/Security/Keystore/SKILL.md +272 -0
  140. package/skills/Security/Network Security Config/SKILL.md +186 -0
  141. package/skills/Security/Obfuscation/SKILL.md +226 -0
  142. package/skills/Security/Proguard/SKILL.md +202 -0
  143. package/skills/Security/R8/SKILL.md +234 -0
  144. package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
  145. package/skills/Security/Root Detection/SKILL.md +220 -0
  146. package/skills/Security/Secure Networking/SKILL.md +220 -0
  147. package/skills/System Integration/AlarmManager/SKILL.md +182 -0
  148. package/skills/System Integration/App Widget/SKILL.md +182 -0
  149. package/skills/System Integration/Deep Link/SKILL.md +187 -0
  150. package/skills/System Integration/Foreground Service/SKILL.md +212 -0
  151. package/skills/System Integration/Notification/SKILL.md +237 -0
  152. package/skills/System Integration/WorkManager/SKILL.md +256 -0
  153. package/skills/System Integration/clipboard/SKILL.md +155 -0
  154. package/skills/System Integration/share-intent/SKILL.md +182 -0
  155. package/skills/Testing/Compose Testing/SKILL.md +296 -0
  156. package/skills/Testing/Espresso/SKILL.md +292 -0
  157. package/skills/Testing/Fake Data/SKILL.md +245 -0
  158. package/skills/Testing/Integration Testing/SKILL.md +288 -0
  159. package/skills/Testing/Mocking/SKILL.md +229 -0
  160. package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
  161. package/skills/Testing/UI Testing/SKILL.md +293 -0
  162. package/skills/Testing/Unit Testing/SKILL.md +309 -0
  163. package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
  164. package/skills/UI System/Compose/SKILL.md +296 -0
  165. package/skills/UI System/Compose Animation/SKILL.md +281 -0
  166. package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
  167. package/skills/UI System/Compose Navigation/SKILL.md +255 -0
  168. package/skills/UI System/Compose Performance/SKILL.md +274 -0
  169. package/skills/UI System/Design System/SKILL.md +217 -0
  170. package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
  171. package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
  172. package/skills/UI System/Loading Strategy/SKILL.md +254 -0
  173. package/skills/UI System/Material 3/SKILL.md +279 -0
  174. package/skills/UI System/RTL/SKILL.md +179 -0
  175. package/src/index.ts +182 -0
  176. package/tsconfig.json +19 -0
@@ -0,0 +1,345 @@
1
+ ---
2
+ name: hilt
3
+ description: >
4
+ Hilt dependency injection setup and patterns for Android.
5
+ Load this skill when setting up Hilt, defining modules, injecting into
6
+ Android components, scoping dependencies, or providing third-party libraries.
7
+ ---
8
+
9
+ # Hilt
10
+
11
+ ## Overview
12
+ Hilt is Android's recommended DI framework built on top of Dagger. It reduces Dagger boilerplate by providing standard components and scopes for Android classes. Hilt generates DI code at compile time — no reflection, no runtime overhead.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - **One scope per lifetime** — match dependency scope to its actual lifetime
19
+ - Never inject into constructors of Android framework classes — use `@Inject` on fields or use Hilt entry points
20
+ - Prefer **constructor injection** over field injection everywhere possible
21
+ - Modules provide dependencies the constructor can't — third-party libs, interfaces, context-dependent types
22
+ - **`@Singleton`** is application-scoped — use sparingly, only for truly shared state
23
+
24
+ ---
25
+
26
+ ## Setup
27
+
28
+ ```toml
29
+ [versions]
30
+ hilt = "2.51.1"
31
+
32
+ [libraries]
33
+ hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
34
+ hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
35
+ hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" }
36
+
37
+ [plugins]
38
+ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
39
+ ```
40
+
41
+ ```kotlin
42
+ // build.gradle.kts (root)
43
+ plugins {
44
+ alias(libs.plugins.hilt) apply false
45
+ }
46
+
47
+ // build.gradle.kts (app)
48
+ plugins {
49
+ alias(libs.plugins.hilt)
50
+ alias(libs.plugins.ksp)
51
+ }
52
+
53
+ dependencies {
54
+ implementation(libs.hilt.android)
55
+ ksp(libs.hilt.compiler)
56
+ implementation(libs.hilt.navigation.compose)
57
+ }
58
+ ```
59
+
60
+ ```kotlin
61
+ // ✅ Application class — required
62
+ @HiltAndroidApp
63
+ class MyApplication : Application()
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Constructor Injection
69
+
70
+ ```kotlin
71
+ // ✅ Preferred — inject via constructor
72
+ class UserRepository @Inject constructor(
73
+ private val userDao: UserDao,
74
+ private val userApi: UserApi,
75
+ private val mapper: UserMapper
76
+ ) {
77
+ // Hilt provides all dependencies automatically
78
+ }
79
+
80
+ class UserMapper @Inject constructor() {
81
+ fun toDomain(entity: UserEntity): User = TODO()
82
+ }
83
+
84
+ // ✅ ViewModel — use @HiltViewModel
85
+ @HiltViewModel
86
+ class UserListViewModel @Inject constructor(
87
+ private val repository: UserRepository,
88
+ private val savedStateHandle: SavedStateHandle
89
+ ) : ViewModel()
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Hilt Modules
95
+
96
+ ```kotlin
97
+ // ✅ @Module + @InstallIn — provides dependencies Hilt can't construct automatically
98
+
99
+ // Singleton module — app-scoped dependencies
100
+ @Module
101
+ @InstallIn(SingletonComponent::class)
102
+ object NetworkModule {
103
+
104
+ @Provides
105
+ @Singleton
106
+ fun provideOkHttpClient(): OkHttpClient =
107
+ OkHttpClient.Builder()
108
+ .connectTimeout(30, TimeUnit.SECONDS)
109
+ .build()
110
+
111
+ @Provides
112
+ @Singleton
113
+ fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
114
+ Retrofit.Builder()
115
+ .baseUrl("https://api.example.com/")
116
+ .client(okHttpClient)
117
+ .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
118
+ .build()
119
+
120
+ @Provides
121
+ @Singleton
122
+ fun provideUserApi(retrofit: Retrofit): UserApi =
123
+ retrofit.create(UserApi::class.java)
124
+ }
125
+
126
+ @Module
127
+ @InstallIn(SingletonComponent::class)
128
+ object DatabaseModule {
129
+
130
+ @Provides
131
+ @Singleton
132
+ fun provideDatabase(@ApplicationContext context: Context): AppDatabase =
133
+ Room.databaseBuilder(context, AppDatabase::class.java, "app_db")
134
+ .addMigrations(MIGRATION_1_2)
135
+ .build()
136
+
137
+ @Provides
138
+ fun provideUserDao(database: AppDatabase): UserDao = database.userDao()
139
+
140
+ @Provides
141
+ fun provideOrderDao(database: AppDatabase): OrderDao = database.orderDao()
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Binding Interfaces
148
+
149
+ ```kotlin
150
+ // ✅ Bind interface to implementation
151
+ @Module
152
+ @InstallIn(SingletonComponent::class)
153
+ abstract class RepositoryModule {
154
+
155
+ @Binds
156
+ @Singleton
157
+ abstract fun bindUserRepository(
158
+ impl: UserRepositoryImpl
159
+ ): UserRepository
160
+
161
+ @Binds
162
+ abstract fun bindAnalytics(
163
+ impl: FirebaseAnalyticsImpl
164
+ ): Analytics
165
+ }
166
+
167
+ // ✅ @Binds is more efficient than @Provides for interface binding
168
+ // Use @Provides only when you need to call a constructor or factory
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Scopes
174
+
175
+ ```kotlin
176
+ // ✅ Scope reference
177
+ @Singleton // lives as long as Application
178
+ @ActivityRetainedScoped // lives as long as ViewModel (survives rotation)
179
+ @ActivityScoped // lives as long as Activity
180
+ @FragmentScoped // lives as long as Fragment
181
+ @ViewScoped // lives as long as View
182
+ @ServiceScoped // lives as long as Service
183
+
184
+ // ✅ Example — screen-level scope
185
+ @Module
186
+ @InstallIn(ActivityRetainedComponent::class)
187
+ object CartModule {
188
+
189
+ @Provides
190
+ @ActivityRetainedScoped
191
+ fun provideCart(): ShoppingCart = ShoppingCart()
192
+ }
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Qualifiers
198
+
199
+ ```kotlin
200
+ // ✅ Distinguish multiple bindings of the same type
201
+ @Qualifier
202
+ @Retention(AnnotationRetention.BINARY)
203
+ annotation class AuthInterceptorOkHttpClient
204
+
205
+ @Qualifier
206
+ @Retention(AnnotationRetention.BINARY)
207
+ annotation class LoggingInterceptorOkHttpClient
208
+
209
+ @Module
210
+ @InstallIn(SingletonComponent::class)
211
+ object NetworkModule {
212
+
213
+ @Provides
214
+ @Singleton
215
+ @AuthInterceptorOkHttpClient
216
+ fun provideAuthOkHttpClient(authInterceptor: AuthInterceptor): OkHttpClient =
217
+ OkHttpClient.Builder()
218
+ .addInterceptor(authInterceptor)
219
+ .build()
220
+
221
+ @Provides
222
+ @Singleton
223
+ @LoggingInterceptorOkHttpClient
224
+ fun provideLoggingOkHttpClient(): OkHttpClient =
225
+ OkHttpClient.Builder()
226
+ .addInterceptor(HttpLoggingInterceptor())
227
+ .build()
228
+ }
229
+
230
+ // ✅ Using qualifier at injection site
231
+ class UserRepository @Inject constructor(
232
+ @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
233
+ )
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Injecting Into Android Components
239
+
240
+ ```kotlin
241
+ // ✅ Activity
242
+ @AndroidEntryPoint
243
+ class MainActivity : ComponentActivity() {
244
+ // Field injection (only when constructor injection is impossible)
245
+ @Inject lateinit var analytics: Analytics
246
+ }
247
+
248
+ // ✅ Fragment
249
+ @AndroidEntryPoint
250
+ class UserFragment : Fragment() {
251
+ private val viewModel: UserViewModel by viewModels()
252
+ }
253
+
254
+ // ✅ Compose — hiltViewModel()
255
+ @Composable
256
+ fun UserScreen(
257
+ viewModel: UserViewModel = hiltViewModel()
258
+ ) { ... }
259
+
260
+ // ✅ WorkManager
261
+ @HiltWorker
262
+ class SyncWorker @AssistedInject constructor(
263
+ @Assisted context: Context,
264
+ @Assisted params: WorkerParameters,
265
+ private val syncEngine: SyncEngine
266
+ ) : CoroutineWorker(context, params) {
267
+ override suspend fun doWork(): Result = TODO()
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ## Entry Points (Non-Hilt Classes)
274
+
275
+ ```kotlin
276
+ // ✅ Access Hilt graph from non-Hilt class (e.g., ContentProvider, custom View)
277
+ @EntryPoint
278
+ @InstallIn(SingletonComponent::class)
279
+ interface UserRepositoryEntryPoint {
280
+ fun userRepository(): UserRepository
281
+ }
282
+
283
+ // Usage
284
+ val entryPoint = EntryPointAccessors.fromApplication(
285
+ context.applicationContext,
286
+ UserRepositoryEntryPoint::class.java
287
+ )
288
+ val repository = entryPoint.userRepository()
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Testing with Hilt
294
+
295
+ ```kotlin
296
+ // ✅ Replace module in tests
297
+ @HiltAndroidTest
298
+ class UserRepositoryTest {
299
+
300
+ @get:Rule
301
+ val hiltRule = HiltAndroidRule(this)
302
+
303
+ @Inject
304
+ lateinit var repository: UserRepository
305
+
306
+ @Before
307
+ fun setUp() { hiltRule.inject() }
308
+
309
+ @Test
310
+ fun testGetUsers() { TODO() }
311
+ }
312
+
313
+ // ✅ Replace a binding for tests
314
+ @UninstallModules(NetworkModule::class)
315
+ @HiltAndroidTest
316
+ class FakeNetworkTest {
317
+
318
+ @Module
319
+ @InstallIn(SingletonComponent::class)
320
+ object FakeNetworkModule {
321
+ @Provides
322
+ fun provideUserApi(): UserApi = FakeUserApi()
323
+ }
324
+ }
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Anti-Patterns
330
+
331
+ - Field injection (`@Inject lateinit var`) in non-Android classes — use constructor injection
332
+ - `@Singleton` on everything — wastes memory, creates hidden shared state
333
+ - Putting business logic in Hilt modules — modules only provide/bind, no logic
334
+ - Injecting `Context` directly — use `@ApplicationContext` or `@ActivityContext`
335
+ - Using `ServiceLocator` pattern alongside Hilt — pick one
336
+ - Circular dependencies — redesign with interfaces or lazy injection
337
+
338
+ ---
339
+
340
+ ## Related Skills
341
+ - `dagger` — Dagger internals when Hilt isn't sufficient
342
+ - `koin` — alternative DI framework
343
+ - `annotation-processing` — KSP setup for Hilt code generation
344
+ - `viewmodel` — @HiltViewModel pattern
345
+ - `workmanager` — @HiltWorker setup
@@ -0,0 +1,282 @@
1
+ ---
2
+ name: koin
3
+ description: >
4
+ Koin dependency injection setup and patterns for Android and KMP.
5
+ Load this skill when working on a project that uses Koin, setting up
6
+ modules, injecting into Android components, or using Koin in KMP projects.
7
+ ---
8
+
9
+ # Koin
10
+
11
+ ## Overview
12
+ Koin is a lightweight DI framework for Kotlin. Unlike Dagger/Hilt, Koin is a service locator at runtime — no code generation, no annotation processing. It's simpler to set up and KMP-compatible. The tradeoff is runtime resolution errors instead of compile-time errors.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - Koin resolves dependencies at **runtime** — errors surface at app start, not compile time
19
+ - Prefer Hilt for pure Android projects — Koin shines in **KMP** where Hilt isn't available
20
+ - Define dependencies in **modules** — one module per feature or layer
21
+ - Use `single` for singletons, `factory` for new instances, `viewModel` for ViewModels
22
+ - Always run `checkModules()` in tests — catches missing bindings before production
23
+
24
+ ---
25
+
26
+ ## Setup
27
+
28
+ ```toml
29
+ [versions]
30
+ koin = "3.5.6"
31
+ koin-compose = "3.5.6"
32
+
33
+ [libraries]
34
+ koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }
35
+ koin-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin-compose" }
36
+ koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } # KMP
37
+ koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" }
38
+ ```
39
+
40
+ ```kotlin
41
+ // build.gradle.kts
42
+ dependencies {
43
+ implementation(libs.koin.android)
44
+ implementation(libs.koin.compose)
45
+ testImplementation(libs.koin.test)
46
+ }
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Koin Application Setup
52
+
53
+ ```kotlin
54
+ // ✅ Initialize in Application
55
+ class MyApplication : Application() {
56
+ override fun onCreate() {
57
+ super.onCreate()
58
+ startKoin {
59
+ androidLogger(Level.DEBUG)
60
+ androidContext(this@MyApplication)
61
+ modules(
62
+ networkModule,
63
+ databaseModule,
64
+ repositoryModule,
65
+ viewModelModule
66
+ )
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Defining Modules
75
+
76
+ ```kotlin
77
+ // ✅ Network module
78
+ val networkModule = module {
79
+
80
+ single {
81
+ OkHttpClient.Builder()
82
+ .connectTimeout(30, TimeUnit.SECONDS)
83
+ .build()
84
+ }
85
+
86
+ single {
87
+ Retrofit.Builder()
88
+ .baseUrl("https://api.example.com/")
89
+ .client(get()) // get() resolves OkHttpClient
90
+ .addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
91
+ .build()
92
+ }
93
+
94
+ single<UserApi> { get<Retrofit>().create(UserApi::class.java) }
95
+ }
96
+
97
+ // ✅ Database module
98
+ val databaseModule = module {
99
+
100
+ single {
101
+ Room.databaseBuilder(androidContext(), AppDatabase::class.java, "app_db")
102
+ .addMigrations(MIGRATION_1_2)
103
+ .build()
104
+ }
105
+
106
+ single { get<AppDatabase>().userDao() }
107
+ single { get<AppDatabase>().orderDao() }
108
+ }
109
+
110
+ // ✅ Repository module
111
+ val repositoryModule = module {
112
+ single<UserRepository> { UserRepositoryImpl(get(), get(), get()) }
113
+ single { UserMapper() }
114
+ }
115
+
116
+ // ✅ ViewModel module
117
+ val viewModelModule = module {
118
+ viewModel { UserListViewModel(get()) }
119
+ viewModel { parameters -> UserDetailViewModel(get(), parameters.get()) }
120
+ }
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Scopes
126
+
127
+ ```kotlin
128
+ // single — one instance for the entire app lifetime
129
+ // factory — new instance every time it's requested
130
+ // scoped — one instance per defined scope lifetime
131
+
132
+ val sessionModule = module {
133
+
134
+ // ✅ Scoped to a session
135
+ scope<UserSession> {
136
+ scoped { CartRepository(get()) }
137
+ scoped { CheckoutViewModel(get()) }
138
+ }
139
+ }
140
+
141
+ // ✅ Create and close scope
142
+ val scope = getKoin().createScope("session_1", named<UserSession>())
143
+ val cart = scope.get<CartRepository>()
144
+ scope.close() // releases scoped instances
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Injection in Android Components
150
+
151
+ ```kotlin
152
+ // ✅ Activity / Fragment — by inject()
153
+ class UserFragment : Fragment() {
154
+ private val viewModel: UserListViewModel by viewModel()
155
+ private val repository: UserRepository by inject()
156
+ }
157
+
158
+ // ✅ Compose — koinViewModel()
159
+ @Composable
160
+ fun UserScreen(
161
+ viewModel: UserListViewModel = koinViewModel()
162
+ ) { ... }
163
+
164
+ // ✅ ViewModel with parameters
165
+ @Composable
166
+ fun UserDetailScreen(userId: String) {
167
+ val viewModel: UserDetailViewModel = koinViewModel(
168
+ parameters = { parametersOf(userId) }
169
+ )
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Qualifiers
176
+
177
+ ```kotlin
178
+ // ✅ Named bindings — distinguish same type
179
+ val networkModule = module {
180
+ single(named("auth")) {
181
+ OkHttpClient.Builder()
182
+ .addInterceptor(get<AuthInterceptor>())
183
+ .build()
184
+ }
185
+ single(named("logging")) {
186
+ OkHttpClient.Builder()
187
+ .addInterceptor(HttpLoggingInterceptor())
188
+ .build()
189
+ }
190
+ }
191
+
192
+ // ✅ Inject with qualifier
193
+ class UserRepository(
194
+ private val client: OkHttpClient = get(named("auth"))
195
+ )
196
+ ```
197
+
198
+ ---
199
+
200
+ ## KMP Setup (commonMain)
201
+
202
+ ```kotlin
203
+ // ✅ Koin works in commonMain — no Android dependency
204
+ // commonMain
205
+ val sharedModule = module {
206
+ single { UserRepository(get(), get()) }
207
+ single { UserMapper() }
208
+ single { HttpClient { /* Ktor config */ } }
209
+ }
210
+
211
+ // androidMain
212
+ val androidModule = module {
213
+ single { AndroidLogger() }
214
+ viewModel { UserListViewModel(get()) }
215
+ }
216
+
217
+ // iosMain — use Koin in Swift via KMP
218
+ // val iosModule = module { ... }
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Testing
224
+
225
+ ```kotlin
226
+ // ✅ checkModules — verify all bindings resolve
227
+ class KoinModuleTest : KoinTest {
228
+
229
+ @Test
230
+ fun verifyKoinModules() {
231
+ checkModules {
232
+ modules(networkModule, databaseModule, repositoryModule, viewModelModule)
233
+ }
234
+ }
235
+ }
236
+
237
+ // ✅ Override bindings in tests
238
+ @Test
239
+ fun testWithFakeDependency() {
240
+ startKoin {
241
+ modules(
242
+ module {
243
+ single<UserRepository> { FakeUserRepository() }
244
+ viewModel { UserListViewModel(get()) }
245
+ }
246
+ )
247
+ }
248
+ // test...
249
+ stopKoin()
250
+ }
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Koin vs Hilt
256
+
257
+ | | Koin | Hilt |
258
+ |--|------|------|
259
+ | Error detection | Runtime | Compile-time |
260
+ | Setup complexity | Low | Medium |
261
+ | KMP support | ✅ Yes | ❌ No |
262
+ | Code generation | ❌ No | ✅ Yes |
263
+ | Android integration | Good | Excellent |
264
+ | Recommended for | KMP, simple apps | Android-only |
265
+
266
+ ---
267
+
268
+ ## Anti-Patterns
269
+
270
+ - Not calling `checkModules()` in tests — runtime errors reach production
271
+ - Using `inject()` (lazy) when `get()` (eager) is needed for initialization order
272
+ - Defining all bindings in one giant module — split by feature/layer
273
+ - Using `single` for everything — `factory` for stateless dependencies
274
+ - Not closing scopes — memory leaks for scoped dependencies
275
+
276
+ ---
277
+
278
+ ## Related Skills
279
+ - `hilt` — preferred DI for Android-only projects
280
+ - `dagger` — compile-time DI underlying Hilt
281
+ - `kmp` — Koin in multiplatform projects
282
+ - `viewmodel` — ViewModel injection with Koin