Kotlin Multiplatform ViewModel 中的方法未从 Compose 屏幕调用

问题描述 投票:0回答:2

我正在开发一个 Kotlin 多平台 (KMP) 项目,我遇到一个问题:当我从 Compose 屏幕触发 ViewModel 中的方法时,该方法不会被调用。我的 ViewModel 位于 commonMain 模块中,并实现 KoinComponent 进行依赖注入。但是,当我尝试从 Compose 屏幕中的 ViewModel 调用方法时,它不会被执行,并且不会出现该方法的日志。

commonMain 中的代码(RegistrationViewModel)

class RegistrationViewModel : CoroutineViewModel(), KoinComponent {

    fun signUp(request: SignUpRequest) {
        println("signUp method called with request: $request")
    }
}

androidMain(注册屏幕)中的代码:

@Composable
fun RegistrationScreen(
    onSignInClicked: () -> Unit,
    onRegisterButtonClicked: () -> Unit,
    navigateToMainScreen: () -> Unit
) {
    val viewModel = remember { RegistrationViewModel() }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val loginValue = remember { mutableStateOf("") }
        val emailValue = remember { mutableStateOf("") }
        val passwordValue = remember { mutableStateOf("") }

        FPButton(text = "Sign In", onClick = {
            val signUpRequest = SignUpRequest(
                name = loginValue.value,
                emailAddress = emailValue.value,
                password = passwordValue.value
            )
            println("Button clicked, calling signUp()")
            viewModel.signUp(signUpRequest)
        })
    }
}

问题: 当我单击“登录”按钮时,我看到日志“单击按钮,调用signUp()”,但来自signUp()方法的日志(“使用请求调用的signUp方法:$request”)从未出现。这表明该方法没有被执行。

我尝试过的: 将记住 { RegistrationViewModel() } 替换为 koinViewModel():

val viewModel: RegistrationViewModel = koinViewModel()

这并没有解决问题。

问题

为什么 ViewModel 没有调用方法signUp()?

这可能与 KMP 项目中 commonMain 中创建 ViewModel 的方式有关吗?

在带有 Koin 的 KMP 上下文中使用 Remember { RegistrationViewModel() } 是否有问题?

android kotlin android-jetpack-compose android-viewmodel kotlin-multiplatform
2个回答
0
投票
import org.koin.dsl.module
import org.koin.androidx.viewmodel.dsl.viewModel

val appModule = module {
    viewModel { RegistrationViewModel() }
}


import org.koin.androidx.compose.getViewModel

@Composable
fun RegistrationScreen(
    onSignInClicked: () -> Unit,
    onRegisterButtonClicked: () -> Unit,
    navigateToMainScreen: () -> Unit
) {
    // Use Koin’s getViewModel() to inject RegistrationViewModel
    val viewModel: RegistrationViewModel = getViewModel()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val loginValue = remember { mutableStateOf("") }
        val emailValue = remember { mutableStateOf("") }
        val passwordValue = remember { mutableStateOf("") }

        FPButton(text = "Sign In", onClick = {
            val signUpRequest = SignUpRequest(
                name = loginValue.value,
                emailAddress = emailValue.value,
                password = passwordValue.value
            )
            println("Button clicked, calling signUp()")
            viewModel.signUp(signUpRequest)  // This should now be called properly
        })
    }
}

解释 Koin 的 getViewModel():此函数确保 RegistrationViewModel 正确注入 Koin 并在 Compose 中使用正确的生命周期进行管理。 避免

remember { RegistrationViewModel() }
:直接将remember与RegistrationViewModel一起使用会绕过Koin并且不提供生命周期感知,这在需要通过依赖注入来管理共享组件的KMP项目中尤其重要。


0
投票

在 Kotlin Multiplatform 中,您可以按如下方式实例化 ViewModel:

val viewModel = viewModel { RegistrationViewModel() }

来源:Common ViewModelufeff

© www.soinside.com 2019 - 2024. All rights reserved.