Skip to content

ViewModel

Koin 透過 koin-core-viewmodel 模組提供多平台 ViewModel 支援。這讓您可以在所有 Kotlin Multiplatform 目標中宣告並注入 AndroidX ViewModel 執行個體。

設定 (Setup)

新增核心 ViewModel 相依性:

kotlin
// build.gradle.kts (commonMain)
implementation("io.insert-koin:koin-core-viewmodel:$koin_version")

對於特定平台的注入 API,請新增:

kotlin
// Android
implementation("io.insert-koin:koin-android:$koin_version")

// Compose Multiplatform
implementation("io.insert-koin:koin-compose-viewmodel:$koin_version")

宣告 ViewModel

編譯器外掛程式 DSL (Compiler Plugin DSL)

kotlin
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

val appModule = module {
    viewModel<UserViewModel>()
}

註解 (Annotations)

kotlin
@KoinViewModel
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

經典 DSL (Classic DSL)

kotlin
val appModule = module {
    // 使用建構函式參照
    viewModelOf(::UserViewModel)

    // 使用 Lambda
    viewModel { UserViewModel(get()) }
}

包含參數的 ViewModel

在注入時使用 @InjectedParam 傳遞參數:

編譯器外掛程式 DSL (Compiler Plugin DSL)

kotlin
class DetailViewModel(
    @InjectedParam val itemId: String,
    private val repository: DetailRepository
) : ViewModel()

val appModule = module {
    viewModel<DetailViewModel>()
}

註解 (Annotations)

kotlin
@KoinViewModel
class DetailViewModel(
    @InjectedParam val itemId: String,
    private val repository: DetailRepository
) : ViewModel()

經典 DSL (Classic DSL)

kotlin
val appModule = module {
    viewModel { params ->
        DetailViewModel(
            itemId = params.get(),
            repository = get()
        )
    }
}

ViewModel 作用域 (ViewModel Scope)

需要自己作用域相依性的 ViewModel 會使用 viewModelScope 原型。在 viewModelScope 內宣告的相依性會與 ViewModel 的生命週期繫結。

編譯器外掛程式 DSL (Compiler Plugin DSL)

kotlin
val appModule = module {
    viewModelScope {
        scoped<UserCache>()
        scoped<UserRepository>()
        viewModel<UserViewModel>()
    }
}

註解 (Annotations)

kotlin
@ViewModelScope
class UserCache

@ViewModelScope
class UserRepository(private val cache: UserCache)

@KoinViewModel
@ViewModelScope
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

經典 DSL (Classic DSL)

kotlin
val appModule = module {
    viewModelScope {
        scoped { UserCache() }
        scoped { UserRepository(get()) }
        viewModel { UserViewModel(get()) }
    }
}

INFO

viewModelScope 內的相依性會在首次存取 ViewModel 時建立,並在清除 ViewModel 時銷毀。

注入 ViewModel

在 Compose (多平台) 中

在 Composable 函式中使用 koinViewModel()

kotlin
@Composable
fun UserScreen() {
    val viewModel = koinViewModel<UserViewModel>()
    // 或使用參數
    val detailVM = koinViewModel<DetailViewModel> { parametersOf("item_123") }
}

在 Android 中

在 Activity 或 Fragment 中使用 by viewModel() 委派:

kotlin
class UserActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModel()

    // 使用參數
    private val detailVM: DetailViewModel by viewModel { parametersOf("item_123") }
}

SavedStateHandle

SavedStateHandle 新增至您的 ViewModel 建構函式中 — Koin 會自動注入:

kotlin
@KoinViewModel
class MyViewModel(
    private val handle: SavedStateHandle,
    private val repository: UserRepository
) : ViewModel() {

    val userId: String? = handle["userId"]
}
kotlin
val appModule = module {
    viewModel<MyViewModel>()  // 編譯器外掛程式 DSL
    // 或
    viewModelOf(::MyViewModel)  // 經典 DSL
}

快速參考 (Quick Reference)

方法 (Approach)模組宣告作用域宣告
編譯器外掛程式 DSLviewModel<MyVM>()viewModelScope { viewModel<MyVM>() }
註解@KoinViewModel@KoinViewModel @ViewModelScope
經典 DSLviewModelOf(::MyVM)viewModelScope { viewModelOf(::MyVM) }
平台注入 API
ComposekoinViewModel<MyVM>()
Androidby viewModel()

特定平台的特性

  • Android:請參閱 Android ViewModel 以了解 Activity/Fragment 共享、導航圖 (Navigation Graph) 作用域。
  • Compose:請參閱 Compose ViewModel 以了解 Compose 特定的 API。

後續步驟