Do you share the view model in KMP between Android...
# multiplatform
a
Do you share the view model in KMP between Android and iOS? or create a view model for each one
c
Since I come from android land, I've been starting out with @Tlaster’s precompose library. so all of my navigation-compose and viewmodel knowledge transfers. i plan to share vms between them
a
Yes but that only for compose multiplatform, I see no easy way and efficient to share view model between iOS and Android
c
oh. you're right. sorry!
👍 1
a
No need to be
r
No need to be
idk why I read this “you need to be” at first and I was shocked xD
😅 3
m
For compose multiplatform, yeah. Personally, I have a common class for models. iOs uses it as it is, android wraps the instance inside an android viewmodel.
👍 1
a
So the state of your ui of the view model is shared, is that what you mean?
m
yeah, the only thing I add in android is the viewmodelScope
👍 1
for example, common layer:
Copy code
class MLSearchViewModel : CustomScopedViewModel() {

    var searchState by mutableStateOf(ViewModelValue<MLSearch>(MLSearch(), false, ""))
    private var currentTerms = ""

    fun loadSearch(terms : String){
        currentTerms = terms
        EventTracer.instance.trace("search_${terms}_vm", "mainview", getTimeMillis())
        getScopeProvider().getScope().launch {
            MLSearchRepository.get().getSearchResults(terms).collect{
                setState(it)
            }
        }
    }

    private fun setState(repoData : RepositoryResult<MLSearch>) {
        if(repoData.isSuccessful()){
            repoData.getValue()?.let { paginatedData->
                searchState = ViewModelValue(paginatedData, true, "")
            }
        } else {
            var newState = ViewModelValue<MLSearch>(MLSearch(), false, repoData.getMessage())
            searchState = newState
        }
        EventTracer.instance.trace("search_${currentTerms}_vm", "mainview", getTimeMillis())
    }
}
android layer:
Copy code
abstract class CustomScopedViewModel : ScopedViewModel {
    private var scopeProvider : ScopeProvider = ScopeProvider.createForUI()
    override fun getScopeProvider(): ScopeProvider {
        return scopeProvider
    }
    override fun setScopeProvider(provider: ScopeProvider) {
        scopeProvider.cancel()
        scopeProvider = provider
    }
}

interface ScopedViewModel {
    fun getScopeProvider() : ScopeProvider
    fun setScopeProvider(provider : ScopeProvider)
}
Copy code
class AndroidMLSearchViewModel : AndroidCustomScopedViewModel() {
    val viewModel  = MLSearchViewModel()
    init {
        viewModel.setScopeProvider(this.getScopeProvider())
    }
    fun loadSearch(terms : String) {
        viewModel.loadSearch(terms)
    }
}
ios composable:
Copy code
companion object{
        @Composable
        fun Render(viewModel: MLSearchViewModel? = null){
            val model = viewModel ?: remember { MLSearchViewModel() }
            val searchResult = model.searchState
            MainView.Render(searchResult) {
                model.loadSearch(it)
            }
        }
    }
👍 1
android's:
Copy code
companion object {
        @Composable
        fun Render(viewModel: AndroidMLSearchViewModel? = null){
            val model = viewModel ?: viewModel()
            val searchResult = model.viewModel.searchState
            MainView.Render(searchResult) {
                model.viewModel.loadSearch(it)
            }
        }
    }
I mean to fuse both without using external sources, just to learn. there are libraries around for viewmodels. It does not look hard to do while using compose, though.
👍 1
319 Views