koin-patterns について
koin-patterns は、Kotlin の Koin による依存性注入を解説するスキルです。Android 開発者向けに、モジュール設定、ライフサイクルスコープ、ViewModel 注入、修飾子、テストを扱います。
主な機能
- 01Koin モジュールの設定
- 02シングルトンとファクトリーの定義
- 03スコープと修飾子の利用
- 04Compose での ViewModel 注入
- 05Koin を使ったテスト
活用シーン
- 01アプリ依存関係の整理
- 02ライフサイクルに応じたオブジェクトの提供
- 03Compose 画面への ViewModel 注入
- 04Koin モジュールを使ったコードのテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ ahmed3elshaer/ everything-claude-code-mobile --skill koin-patternsインストール後、Claude Code で/koin-patternsを入力して読み込まれたか確認します。
詳細
Koin の依存性注入
Koin を使った Kotlin 向けの実用的な DI です。
モジュールの設定
// AppModule.kt
val appModule = module {
// Singletons
single<AppDatabase> { Room.databaseBuilder(...).build() }
single { get<AppDatabase>().userDao() }
// Factories (new instance each time)
factory { DateFormatter() }
}
// NetworkModule.kt
val networkModule = module {
single<HttpClient> {
HttpClient(OkHttp) {
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
}
}
single<AuthApi> { AuthApiImpl(get()) }
single<UserApi> { UserApiImpl(get()) }
}
// FeatureModule.kt
val homeModule = module {
// Repository
single<HomeRepository> { HomeRepositoryImpl(get(), get()) }
// Use Cases
factory { GetItemsUseCase(get()) }
factory { GetItemUseCase(get()) }
// ViewModel
viewModel { HomeViewModel(get()) }
}
アプリケーションの設定
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApp)
modules(
appModule,
networkModule,
homeModule,
detailModule
)
}
}
}
ViewModel の注入
// In Compose
@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
val state by viewModel.state.collectAsStateWithLifecycle()
// ...
}
// With parameters
@Composable
fun DetailScreen(itemId: String) {
val viewModel: DetailViewModel = koinViewModel { parametersOf(itemId) }
// ...
}
// ViewModel definition with params
viewModel { params ->
DetailViewModel(
itemId = params.get(),
repository = get()
)
}
スコープ
// Activity scope
val activityModule = module {
scope<MainActivity> {
scoped { NavigationController() }
}
}
// Usage
class MainActivity : AppCompatActivity(), KoinScopeComponent {
override val scope: Scope by activityScope()
val nav: NavigationController by inject()
}
修飾子
val networkModule = module {
single(named("auth")) { createAuthClient() }
single(named("default")) { createDefaultClient() }
}
// Usage
class UserApi(
@Named("auth") private val client: HttpClient
)
テスト
class HomeViewModelTest : KoinTest {
@get:Rule
val koinRule = KoinTestRule.create {
modules(testModule)
}
private val testModule = module {
single<HomeRepository> { mockk() }
viewModel { HomeViewModel(get()) }
}
private val viewModel: HomeViewModel by inject()
private val repository: HomeRepository by inject()
@Test
fun `loads items`() = runTest {
coEvery { repository.getItems() } returns Result.success(listOf())
// ...
}
}
覚えておいてください:Koin は実用性を重視しています。モジュールを整理し、ライフサイクルにはスコープを使いましょう。
コメント
Markdown 対応