koin-patterns
Androidアプリ開発で、Koinというライブラリを使って、部品(モジュール)や範囲(スコープ)、画面のデータ管理(ViewModel)を効率的に組み込み、アプリの設計をより柔軟にするSkill。
📜 元の英語説明(参考)
Koin dependency injection patterns for Android with modules, scopes, and ViewModel injection.
🇯🇵 日本人クリエイター向け解説
Androidアプリ開発で、Koinというライブラリを使って、部品(モジュール)や範囲(スコープ)、画面のデータ管理(ViewModel)を効率的に組み込み、アプリの設計をより柔軟にするSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o koin-patterns.zip https://jpskill.com/download/10675.zip && unzip -o koin-patterns.zip && rm koin-patterns.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10675.zip -OutFile "$d\koin-patterns.zip"; Expand-Archive "$d\koin-patterns.zip" -DestinationPath $d -Force; ri "$d\koin-patterns.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
koin-patterns.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
koin-patternsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Koin 依存性注入
Koin を用いた Kotlin 向けのプラグマティックな DI です。
モジュール設定
// AppModule.kt
val appModule = module {
// シングルトン
single<AppDatabase> { Room.databaseBuilder(...).build() }
single { get<AppDatabase>().userDao() }
// ファクトリ (毎回新しいインスタンス)
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 {
// リポジトリ
single<HomeRepository> { HomeRepositoryImpl(get(), get()) }
// ユースケース
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 インジェクション
// Compose での使用例
@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
val state by viewModel.state.collectAsStateWithLifecycle()
// ...
}
// パラメータ付きの場合
@Composable
fun DetailScreen(itemId: String) {
val viewModel: DetailViewModel = koinViewModel { parametersOf(itemId) }
// ...
}
// パラメータ付きの ViewModel 定義
viewModel { params ->
DetailViewModel(
itemId = params.get(),
repository = get()
)
}
スコープ
// Activity スコープ
val activityModule = module {
scope<MainActivity> {
scoped { NavigationController() }
}
}
// 使用例
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() }
}
// 使用例
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 はプラグマティックです。モジュールを整理し、ライフサイクルに合わせてスコープを使用してください。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Koin Dependency Injection
Pragmatic DI for Kotlin with Koin.
Module Setup
// 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()) }
}
Application Setup
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApp)
modules(
appModule,
networkModule,
homeModule,
detailModule
)
}
}
}
ViewModel Injection
// 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()
)
}
Scopes
// 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()
}
Qualifiers
val networkModule = module {
single(named("auth")) { createAuthClient() }
single(named("default")) { createDefaultClient() }
}
// Usage
class UserApi(
@Named("auth") private val client: HttpClient
)
Testing
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())
// ...
}
}
Remember: Koin is pragmatic. Keep modules organized, use scopes for lifecycle.