如何在带有流的可组合屏幕内使用协程?

贝高

我正在使用 jetpack Compose 和 flow,但尝试在可组合屏幕中获取数据时出现错误 LaunchedEffect

@Composable 的调用只能在 @Composable 函数的上下文中发生

在这里我详细说明我的代码的流程

在这里它会产生错误 LaunchedEffect

屏幕

@Composable
fun LoginScreen(
    navController: NavController,
    viewModel: LoginViewModel = hiltViewModel()
) {
  

    Box(
        modifier = Modifier.fillMaxSize().fillMaxHeight()
    ) {
        Column(
            modifier = Modifier.fillMaxWidth().padding(15.dp),
        ) {
            //TextField username
            //TextField password
 
            Button(
                onClick = {
                     // Error  
                     // @Composable invocations can only happen from the context of a @Composable function
                    LaunchedEffect(Unit) {
                        viewModel.login(
                            viewModel.passwordValue.value, viewModel.usernameValue.value
                        )
                    }

                },
               
            ) {
                Text(text = stringResource(id = R.string.login))
            }
        }
    }
}
视图模型
@HiltViewModel
class LoginViewModel @Inject constructor(private val toLogin: ToLogin) : ViewModel() {

    private val _usernameValue = mutableStateOf("")
    val usernameValue: State<String> = _usernameValue

    private val _passwordValue = mutableStateOf("")
    val passwordValue: State<String> = _passwordValue

    fun setUsernameValue(username: String) {
        _usernameValue.value = username
    }

    fun setPasswordValue(password: String) {
        _passwordValue.value = password
    }

     suspend fun login(username: String, password: String) {

        val r = toLogin(username, password);
        r.collect {
            Log.d("XTRACE", it.toString());
        }

    }
}
应用程序接口
class AuthApiSource @Inject constructor(
    private val loginApiService: LoginApiService,
) {
    suspend fun login(username: String, password: String): Result<AccessToken?> = runCatching {

        loginApiService.toLogin(
            username = username,
            password = password,
        ).body();

    }
}
用例
class ToLogin @Inject constructor(private val apiAuth: AuthApiSource) {
    operator fun invoke(username: String, password: String): Flow<Result<AccessToken?>> =
        flow {
            val response = runCatching {
                val token = apiAuth.login(username, password)
                token.getOrThrow()
            }
            emit(response)
        }
}

什么是正确的方法呢?

弗朗西斯

你必须使用rememberCoroutineScope

@Composable
fun LoginScreen(
    navController: NavController,
    viewModel: LoginViewModel = hiltViewModel()
) {

    val scope = rememberCoroutineScope()
    Box(
        modifier = Modifier.fillMaxSize().fillMaxHeight()
    ) {
        Column(
            modifier = Modifier.fillMaxWidth().padding(15.dp),
        ) {
            //TextField username
            //TextField password

            Button(
                onClick = {
                    // Error  
                    // @Composable invocations can only happen from the context of a @Composable function
                    scope.launch {
                        viewModel.login(
                            viewModel.passwordValue.value, viewModel.usernameValue.value
                        )
                    }

                },

                ) {
                Text(text = stringResource(id = R.string.login))
            }
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Andorid Studios中进行可序列化/可组合对

如何在可组合函数回调中调用Kotlin协程?

使用reduceRight()的多参数可组合函数实现

如何在带有Kotlin的Retrofit 2.6.0协程中正确使用暂停乐趣

Jetpack Compose应该如何引用可组合的高阶函数?

如何在Jetpack Compose中从可组合内容导航到活动或片段?

具有可组合形式的动态形式

如何在暂停的协程流中使用回调?

如何在 AngularJS 中定义可组合组件

使用 Spring RouterFunctionDsl 的可组合路由

如何在 Python 中使用带有协程的装饰器?

如何使用 Hilt (Jetpack Compose) 将 ViewModel 注入到可组合函数中

svelte 可以使用可组合函数吗?

如何在可组合中在末尾的行列和开始的表面对齐

如何更新可组合函数内的 RecyclerView 的数据?

android - 如何在Android Jetpack Compose中没有包装器可组合的情况下在列的末尾放置一个项目?

如何从可组合函数中获取当前活动?

中心可组合在屏幕中央

如何在依赖于视图模型的可组合函数中获得预览?

如何使用 React 高阶函数最大化可组合性?

使用 Lambda 更新可组合函数

如何使用 lambda 的返回来更新可组合的状态

如何在可组合中获取意图数据

如何使用 For 循环更新使我的可组合重构?

如何在可组合函数中进行调用(数据库、网络)?

作用域可组合到父可组合

使用 LazyListScope 嵌套可组合项

GoogleMap 可组合占用所有可用的屏幕空间

在可组合物 vue3 中使用道具