jpskill.com
🛠️ 開発・MCP コミュニティ

kmp-di

KMP(Kotlin Multiplatform)環境で、Koinを使ったDependency Injectionの設定や、プラットフォームごとのモジュール定義、手動でのDIパターンなどを活用し、効率的な依存性注入を実現するSkill。

📜 元の英語説明(参考)

Dependency Injection for KMP. Koin multiplatform setup, platform modules, and manual DI patterns.

🇯🇵 日本人クリエイター向け解説

一言でいうと

KMP(Kotlin Multiplatform)環境で、Koinを使ったDependency Injectionの設定や、プラットフォームごとのモジュール定義、手動でのDIパターンなどを活用し、効率的な依存性注入を実現するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o kmp-di.zip https://jpskill.com/download/10671.zip && unzip -o kmp-di.zip && rm kmp-di.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10671.zip -OutFile "$d\kmp-di.zip"; Expand-Archive "$d\kmp-di.zip" -DestinationPath $d -Force; ri "$d\kmp-di.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して kmp-di.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → kmp-di フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

KMP 依存性注入

Koin を用いたクロスプラットフォームな依存性注入。

Koin マルチプラットフォーム設定

依存関係

// build.gradle.kts (shared module)
sourceSets {
    val commonMain by getting {
        dependencies {
            implementation("io.insert-koin:koin-core:${koinVersion}")
            implementation("io.insert-koin:koin-test:${koinVersion}")
        }
    }
    val androidMain by getting {
        dependencies {
            implementation("io.insert-koin:koin-android:${koinVersion}")
        }
    }
}

モジュール定義

// commonMain/kotlin/di/AppModule.kt
val sharedModule = module {
    // ViewModels (Android) / ScreenModels (multiplatform)
    factory { HomeViewModel(get(), get()) }
    factory { DetailViewModel(get()) }

    // Use Cases
    factory { GetUsersUseCase(get()) }
    factory { GetUserDetailUseCase(get()) }

    // Repositories
    single<UserRepository> { UserRepositoryImpl(get(), get()) }

    // Data Sources
    single { UserApi(get()) }
    single { createDatabase(get()) }
}

プラットフォームモジュール

// androidMain/kotlin/di/PlatformModule.kt
val androidPlatformModule = module {
    includes(sharedModule)

    // Android-specific dependencies
    single { android.content.Context() }
    single { PlatformConnectivityMonitor(get()) }
    single { PlatformFileService(get()) }
}

// iosMain/kotlin/di/PlatformModule.kt
val iosPlatformModule = module {
    includes(sharedModule)

    // iOS-specific dependencies
    single { PlatformConnectivityMonitor() }
    single { PlatformFileService() }
}

Koin の起動

Android

// androidMain/kotlin/MyApp.kt
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MyApp)
            modules(androidPlatformModule)
        }
    }
}

iOS

// iosMain/kotlin/di/KoinInit.kt
fun initKoin() {
    startKoin {
        modules(iosPlatformModule)
    }
}

// Called from Swift
// KotlinKMMSharedKt.doInitKoin()

Compose Multiplatform

// commonMain/kotlin/Main.kt
fun main() {
    startKoin {
        modules(sharedModule)
    }

    App()
}

ViewModel の注入

Android (ViewModel)

// androidMain/kotlin/ui/HomeScreen.kt
@Composable
fun HomeScreen(
    viewModel: HomeViewModel = koinViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    HomeContent(state)
}

iOS (ScreenModel)

// commonMain/kotlin/ui/HomeScreen.kt
@Composable
fun HomeScreen() {
    val model = getScreenModel<HomeScreenModel>()
    val state by model.state.collectAsState()

    HomeContent(state)
}

Repository パターン

Factory vs Single

// ✅ factory - 毎回新しいインスタンスを作成
factory { HomeViewModel(get(), get()) }

// ✅ single - 共有インスタンス
single<UserRepository> { UserRepositoryImpl(get(), get()) }

// ✅ scoped - コンポーネントのライフサイクルに紐づく
scoped(HomeScope.homeScope) { HomeData(get()) }

名前付き依存関係

// ✅ 名前付き依存関係
module {
    single(named("default")) { DefaultLogger() }
    single(named("analytics")) { AnalyticsLogger() }

    factory { MyRepository(logger = get(named("default"))) }
}

手動 DI (代替案)

シンプルな Service Locator

// commonMain/kotlin/di/ServiceLocator.kt
object ServiceLocator {
    private val services = mutableMapOf<String, Any>()

    fun <T> get(key: String): T {
        return services[key] as T
    }

    fun register(key: String, service: Any) {
        services[key] = service
    }

    fun init() {
        register("repository", UserRepositoryImpl())
        register("api", UserApi())
    }
}

Pure Kotlin DI

// commonMain/kotlin/di/AppContainer.kt
class AppContainer(
    private val platformService: PlatformService
) {
    val api: UserApi = UserApi()
    val database: AppDatabase = createDatabase()

    val userRepository: UserRepository by lazy {
        UserRepositoryImpl(api, database)
    }

    val homeViewModel: HomeViewModel by lazy {
        HomeViewModel(userRepository, platformService)
    }
}

DI を用いたテスト

// commonTest/kotlin/di/TestModule.kt
val testModule = module {
    single<MockUserService> { MockUserService() }
    single<UserService>(override = true) { get<MockUserService>() }
}

// In tests
@BeforeTest
fun setup() {
    startKoin { modules(testModule) }
}

@AfterTest
fun tearDown() {
    stopKoin()
}

Remember: DI はテストを簡略化します。モックやフェイクを簡単に注入するために使用してください。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

KMP Dependency Injection

Cross-platform dependency injection with Koin.

Koin Multiplatform Setup

Dependencies

// build.gradle.kts (shared module)
sourceSets {
    val commonMain by getting {
        dependencies {
            implementation("io.insert-koin:koin-core:${koinVersion}")
            implementation("io.insert-koin:koin-test:${koinVersion}")
        }
    }
    val androidMain by getting {
        dependencies {
            implementation("io.insert-koin:koin-android:${koinVersion}")
        }
    }
}

Module Definition

// commonMain/kotlin/di/AppModule.kt
val sharedModule = module {
    // ViewModels (Android) / ScreenModels (multiplatform)
    factory { HomeViewModel(get(), get()) }
    factory { DetailViewModel(get()) }

    // Use Cases
    factory { GetUsersUseCase(get()) }
    factory { GetUserDetailUseCase(get()) }

    // Repositories
    single<UserRepository> { UserRepositoryImpl(get(), get()) }

    // Data Sources
    single { UserApi(get()) }
    single { createDatabase(get()) }
}

Platform Modules

// androidMain/kotlin/di/PlatformModule.kt
val androidPlatformModule = module {
    includes(sharedModule)

    // Android-specific dependencies
    single { android.content.Context() }
    single { PlatformConnectivityMonitor(get()) }
    single { PlatformFileService(get()) }
}

// iosMain/kotlin/di/PlatformModule.kt
val iosPlatformModule = module {
    includes(sharedModule)

    // iOS-specific dependencies
    single { PlatformConnectivityMonitor() }
    single { PlatformFileService() }
}

Koin Start

Android

// androidMain/kotlin/MyApp.kt
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MyApp)
            modules(androidPlatformModule)
        }
    }
}

iOS

// iosMain/kotlin/di/KoinInit.kt
fun initKoin() {
    startKoin {
        modules(iosPlatformModule)
    }
}

// Called from Swift
// KotlinKMMSharedKt.doInitKoin()

Compose Multiplatform

// commonMain/kotlin/Main.kt
fun main() {
    startKoin {
        modules(sharedModule)
    }

    App()
}

ViewModel Injection

Android (ViewModel)

// androidMain/kotlin/ui/HomeScreen.kt
@Composable
fun HomeScreen(
    viewModel: HomeViewModel = koinViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    HomeContent(state)
}

iOS (ScreenModel)

// commonMain/kotlin/ui/HomeScreen.kt
@Composable
fun HomeScreen() {
    val model = getScreenModel<HomeScreenModel>()
    val state by model.state.collectAsState()

    HomeContent(state)
}

Repository Pattern

Factory vs Single

// ✅ factory - creates new instance each time
factory { HomeViewModel(get(), get()) }

// ✅ single - shared instance
single<UserRepository> { UserRepositoryImpl(get(), get()) }

// ✅ scoped - tied to component lifetime
scoped(HomeScope.homeScope) { HomeData(get()) }

Named Dependencies

// ✅ Named dependencies
module {
    single(named("default")) { DefaultLogger() }
    single(named("analytics")) { AnalyticsLogger() }

    factory { MyRepository(logger = get(named("default"))) }
}

Manual DI (Alternative)

Simple Service Locator

// commonMain/kotlin/di/ServiceLocator.kt
object ServiceLocator {
    private val services = mutableMapOf<String, Any>()

    fun <T> get(key: String): T {
        return services[key] as T
    }

    fun register(key: String, service: Any) {
        services[key] = service
    }

    fun init() {
        register("repository", UserRepositoryImpl())
        register("api", UserApi())
    }
}

Pure Kotlin DI

// commonMain/kotlin/di/AppContainer.kt
class AppContainer(
    private val platformService: PlatformService
) {
    val api: UserApi = UserApi()
    val database: AppDatabase = createDatabase()

    val userRepository: UserRepository by lazy {
        UserRepositoryImpl(api, database)
    }

    val homeViewModel: HomeViewModel by lazy {
        HomeViewModel(userRepository, platformService)
    }
}

Testing with DI

// commonTest/kotlin/di/TestModule.kt
val testModule = module {
    single<MockUserService> { MockUserService() }
    single<UserService>(override = true) { get<MockUserService>() }
}

// In tests
@BeforeTest
fun setup() {
    startKoin { modules(testModule) }
}

@AfterTest
fun tearDown() {
    stopKoin()
}

Remember: DI simplifies testing. Use it to inject mocks and fakes easily.