Getting Started with Koin Annotations 1.4 in Compose Multiplatform
Getting Started with Koin Annotations 1.4 in Compose Multiplatform 관련
If you've been using Koin's DSL for dependency injection in your Kotlin Multiplatform projects, you might be interested in exploring a more annotation-driven approach. In this guide, Arnaud walks you through migrating a simple Compose Multiplatform application from Koin DSL to the new Koin Annotations 1.4.
Project Overview
We'll be working with the KMP App Template (InsertKoinIO/KMP-App-Template
) from JetBrains, which provides a great starting point for our exploration. The data displayed by the app is from The Metropolitan Museum of Art Collection API. This app already uses Koin for dependency injection. This template implements this simple art gallery application that displays a list of paintings and their details. While the functionality is straightforward, it serves as an excellent example to demonstrate Koin's annotation-based dependency injection. And bonus : it's beautiful to look at.
Setting Up Dependencies
Before diving into the migration, let's ensure we have all the necessary dependencies:
dependencies {
implementation("io.insert-koin:koin-core:3.6.0-beta5")
implementation("io.insert-koin:koin-compose:1.2.0-beta5")
implementation("io.insert-koin:koin-annotations:1.4.0")
implementation("io.insert-koin:koin-ksp-compiler:1.4.0")
}
Don't forget to set up KSP (Kotlin Symbol Processing) in your project, as it's essential for annotation processing.
Project Structure
Our sample application follows a clean architecture approach with the following key components:
- Data Layer:
MuseumAPI
: Handles remote data fetchingMuseumRepository
: Manages data operationsMuseumStorage
: Handles local data persistence
- UI Layer:
- List Screen: Displays paintings grid
- Detail Screen: Shows painting details
- ViewModels: Manages UI state and business logic
Migrating to Koin Annotations
Step 1: View Model Migration
Let's start by migrating our view models from DSL to annotations. Replace the existing DSL module definition:
@Module
@ComponentScan("com.package.screens")
class ViewModelModule
@ViewModel
class PaintingViewModel(val repository: MuseumRepository): ViewModel() {
// Implementation
}
Step 2: Data Layer Migration
Next, let's tackle the data layer components:
@Module
@ComponentScan("com.package.data")
class DataModule
@Singleton
class MuseumRepository (
private val api: MuseumAPI,
private val storage: MuseumStorage
)
@Singleton
class MuseumAPI(private val httpClient: HttpClient)
Step 3: Complex Initializations
For more complex scenarios where you need custom initialization logic, you can use separate functions with the @Single
annotation:
@Module
class NetworkModule {
@Single fun provideHttpClient(json: Json): HttpClient {
return HttpClient {
// Configuration
}
}
Platform-Specific Components
One of the powerful features of Koin Annotations is its support for platform-specific implementations. Here's how to set it up:
// Common Native
@Module expect class NativeModule
expect class PlatformComponent {
fun sayHello(): String
}
// Native Implementation in Android
@Module
@ComponentScan("com.jetbrains.kmpapp.native")
actual class NativeModule
@Single
actual class PlatformComponent (val context: Context) {
actual fun sayHello(): String = "I'm Android $context"
}
// Native Implementation in iOS
@Module
@ComponentScan("com.jetbrains.kmpapp.native")
actual class NativeModule
@Single
actual class PlatformComponent {
actual fun sayHello(): String = "I'm iOS"
}
Benefits of Using Koin Annotations
- 🔸 Cleaner Code: Annotations provide a more declarative and concise way to define dependencies
- 🔸 Better IDE Support: Enhanced code navigation and refactoring capabilities
- 🔸 Compile-Time Validation: Earlier detection of dependency injection issues
- 🔸 Reduced Boilerplate: KSP generates necessary extension functions automatically
- 🔸 Platform-Specific Support: Seamless handling of platform-specific dependencies
Wrapping Up
Migrating from Koin DSL to Annotations might require some initial setup, but the benefits in terms of code clarity and maintainability are well worth it. The annotation-based approach provides a more familiar paradigm for developers coming from other dependency injection frameworks while maintaining Koin's lightweight and Kotlin-first philosophy.
Remember to check out the official Koin documentation for more detailed information and advanced usage scenarios. Tell us what you think!