繁体   English   中英

在 jetpack compose 中正确使用 mutableStateflow 和 Launcheffect

[英]Proper use of mutableStateflow with Launcheffect in jetpack compose

嘿,我在 jetpack compose 中的MutableStateFlow工作。 我正在尝试在下一个屏幕中加载微调器,但它不起作用。 我开始学习jetpack compose。 我没有在jetpack compose中找到正确的方法。 我以传统方式了解MutableStateFlow 我将尝试解释我正在尝试做的事情以及我想要实现的目标。 我在可组合函数中有一个Button ,当我按下Button时,我将进入viewModel并调用viewModelScope.launch中的 api。 在此基础上,我创建了一个名为ResultFetchState的类,它是密封类,在其中我使用了UI state 当我的 api 得到任何东西时,它将路由到成功、错误加载 主要问题是当我使用collectAsState()时,数据正在进行onSuccessonLoading不起作用。 希望你明白这一点。

MainActivityViewModel.kt

class MainActivityViewModel(private val resultRepository: ResultRepository) : ViewModel() {

    val stateResultFetchState = MutableStateFlow<ResultFetchState>(ResultFetchState.OnEmpty)

    fun getSportResult() {
        viewModelScope.launch {
            val result = resultRepository.getSportResult()
            delay(5000)
            result.handleResult(
                onSuccess = { response ->
                    if (response != null) {
                        stateResultFetchState.value = ResultFetchState.IsLoading(false)
                        stateResultFetchState.value = ResultFetchState.OnSuccess(response)
                    } else {
                        stateResultFetchState.value = ResultFetchState.OnEmpty
                    }
                },
                onError = {
                    stateResultFetchState.value =
                        ResultFetchState.OnError(it.errorResponse?.errorMessage)
                }
            )
        }
    }
}

我没有添加我的整个活动代码。 我正在添加我的可组合函数。 如果您需要查看我的整个活动,请单击下面的班级名称。

MainActivity.kt

@OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun SetupView(viewModel: MainActivityViewModel = koinViewModel()) {
        Scaffold(topBar = {
            TopAppBar(
                title = { Text(text = stringResource(id = R.string.app_name)) },
                backgroundColor = getBackgroundColor(),
                elevation = 0.dp
            )
        }, content = { padding ->
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .background(getBackgroundColor())
                    .padding(padding),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Button(onClick = {
                    viewModel.getSportResult()
                }) {
                    Text(text = stringResource(id = R.string.get_result))
                }
            }
        })
        when (val state = viewModel.stateResultFetchState.collectAsState().value) {
            is ResultFetchState.OnSuccess -> {
                logE("data >> ${state.sportResultResponse}")
            }
            is ResultFetchState.IsLoading -> {
                if (state.isLoading) {
                    logE("data loading >")
                    ResultScreen()
                }
            }
            is ResultFetchState.OnError -> {
                logE("data >> ${state.response}")
            }
            is ResultFetchState.OnEmpty -> {}
        }
    }

我虽然在我的生命周期中有问题。 所以我在LaunchedEffect的堆栈溢出中搜索,但仍然无法正常工作。 另一个问题是在我的代码中有任何使用LaunchedEffect我对这个副作用有点困惑。 我的 github 项目链接 谢谢

您正在连续设置stateResultFetchState的值

  fun getSportResult() {
        viewModelScope.launch {
            val result = resultRepository.getSportResult()
            delay(5000)
            result.handleResult(
                onSuccess = { response ->
                    if (response != null) {
                        stateResultFetchState.value = ResultFetchState.IsLoading(false)
                        stateResultFetchState.value = ResultFetchState.OnSuccess(response)
                    } else {
                        stateResultFetchState.value = ResultFetchState.OnEmpty
                    }
                },
                onError = {
                    stateResultFetchState.value =
                        ResultFetchState.OnError(it.errorResponse?.errorMessage)
                }
            )
        }
    }

您可以在获取运动结果之前设置为加载,并在您的用户界面中检查加载是否为真,您需要将其设置为真

fun getSportResult() {
    viewModelScope.launch {
        stateResultFetchState.value = ResultFetchState.IsLoading(true)
        val result = resultRepository.getSportResult()
        delay(5000)
        result.handleResult(
            onSuccess = { response ->
                if (response != null) {
                    stateResultFetchState.value = ResultFetchState.OnSuccess(response)
                } else {
                    stateResultFetchState.value = ResultFetchState.OnEmpty
                }
            },
            onError = {
                stateResultFetchState.value =
                    ResultFetchState.OnError(it.errorResponse?.errorMessage)
            }
        )
    }
}

您的 UI 也存在问题。 即使您正确地获得了加载状态,您也可能能够看到它们,因为 Scaffold 将子项放置在content Composable 中

bodyContentPlaceables.forEach {
            it.place(0, 0)
        }

您可能需要使用覆盖您的内容区域的 Composable 作为根 Comopsable。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM