簡體   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