Hey guy, how do share viewmodels in KMM? Knowing t...
# multiplatform
a
Hey guy, how do share viewmodels in KMM? Knowing that Android view models have lifecycle dependent on the platform?
s
I did this through expect/actual. in commonMain, declare an expect, eg CommonViewModel (with maybe a few expect funs as well). In androidMain, actual this with an Android ViewModel (and possibly some actuals for these funs as well). In iOS Main, just a plain class for the actual (with some actuals for these funs as well).
a
@streetsofboston Okay thanks. Will interface make sense in this context? Does actual/expect have an advantage?
s
I favor interfaces&implementations. But for me actua/expect worked better for ViewModel, since you can have a different/separate class hierarchy, not requiring a single (top) interface.
Eg, on Android, I could do
actual class KmpViewModel : ViewModel() { .....}
and on iOS
actual class KmpViewModel { ... }
and create them (not having them injected) in my native Android or iOS code.
More detailed: commonMain:
Copy code
/**
 * A [ViewModel] expects to be implemented by a platform specific
 * implementation of a View-Model.
 */
expect abstract class ViewModel() {
    /**
     * This method must be called when this [ViewModel] is no longer needed.
     * It cleans up its resources and cancels its scope.
     */
    abstract fun onDestroy()
}

...
...

abstract class BaseViewModel(protected val scope: CoroutineScope, protected val log: Kermit): ViewModel() {
    override fun onDestroy() {
        log.v { "onDestroy called" }
        scope.cancel()
    }
    ...
}
androidMain:
Copy code
/**
 * Android implements the [ViewModel] through its Android lifecycle [androidx.lifecycle.ViewModel].
 */
actual abstract class ViewModel : androidx.lifecycle.ViewModel() {
    override fun onCleared() = onDestroy()

    actual abstract fun onDestroy()
}
iosMain:
Copy code
/**
 * iOS does not provide any platform-specific implementation for a [ViewModel].
 */
actual abstract class ViewModel {
    actual abstract fun onDestroy()
}
a
@streetsofboston Thank you!