← ClaudeAtlas

android-kmp-viewmodellisted

Sharing ViewModel logic across Android and iOS in KMP — CommonViewModel base, StateFlow in shared code, platform wrappers for iOS consumption. Use when building shared presentation logic, moving ViewModel to commonMain, or exposing Flow to Swift. Trigger on: "shared ViewModel", "KMP ViewModel", "commonMain ViewModel", "StateFlow iOS", "KMP presentation".
lenorebreakneck630/claude-zero-to-hero-android-KMP · ★ 1 · AI & Automation · score 64
Install: claude install-skill lenorebreakneck630/claude-zero-to-hero-android-KMP
# KMP ViewModel ## Strategy Keep `ViewModel` class on Android (it owns `viewModelScope`). Move all **state logic** to a platform-agnostic `Presenter` or `CommonViewModel` in `commonMain` that takes an explicit `CoroutineScope`. ## CommonViewModel (`commonMain`) ```kotlin // commonMain — core:domain or feature module abstract class CommonViewModel { private val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) protected fun launch(block: suspend CoroutineScope.() -> Unit): Job = viewModelScope.launch(block = block) open fun onCleared() { viewModelScope.cancel() } } ``` ## Android ViewModel wraps it ```kotlin // androidMain class TaskListViewModel( private val getTasks: GetTasksUseCase, ) : ViewModel() { private val _state = MutableStateFlow(TaskListState()) val state: StateFlow<TaskListState> = _state.asStateFlow() init { viewModelScope.launch { getTasks().collect { tasks -> _state.update { it.copy(tasks = tasks) } } } } } ``` ## iOS Swift wrapper (StateFlow → Combine) ```kotlin // iosMain — thin wrapper so Swift can observe class TaskListIosViewModel( private val getTasks: GetTasksUseCase, ) : CommonViewModel() { private val _state = MutableStateFlow(TaskListState()) val state: StateFlow<TaskListState> = _state.asStateFlow() init { launch { getTasks().collect { tasks -> _state.update { i