mcpField
K
koin-patterns

koin-patterns

github.com/ahmed3elshaer開発6642 回インストール19 週間前に更新
リポジトリ

koin-patterns について

koin-patterns は、Kotlin の Koin による依存性注入を解説するスキルです。Android 開発者向けに、モジュール設定、ライフサイクルスコープ、ViewModel 注入、修飾子、テストを扱います。

主な機能

  1. 01Koin モジュールの設定
  2. 02シングルトンとファクトリーの定義
  3. 03スコープと修飾子の利用
  4. 04Compose での ViewModel 注入
  5. 05Koin を使ったテスト

活用シーン

  1. 01アプリ依存関係の整理
  2. 02ライフサイクルに応じたオブジェクトの提供
  3. 03Compose 画面への ViewModel 注入
  4. 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 は実用性を重視しています。モジュールを整理し、ライフサイクルにはスコープを使いましょう。

コメント