You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose:为TextField提供初始值并实现跨屏状态同步

解决方案

方案一:无需Flow的优化实现

核心思路是区分配置变更和从Summary页返回两种场景,只在金额确实发生外部修改时同步输入框状态,同时通过rememberSaveable保留配置变更时的输入内容。

1. 优化ViewModel(可选,增强进程被杀恢复能力)

用SavedStateHandle存储金额,确保进程被杀后状态不丢失:

internal class PaymentFlowViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    private val AMOUNT_KEY = "payment_flow_amount"
    var amount: String
        get() = savedStateHandle[AMOUNT_KEY] ?: ""
        set(value) = savedStateHandle.set(AMOUNT_KEY, value)
}

2. 修改AmountInputRoute

将LaunchedEffect的触发条件改为监听initialAmount变化,仅当外部金额与当前输入状态不一致时才同步:

@Composable
internal fun AmountInputRoute(
    initialAmount: String,
    onAmountConfirmed: (String) -> Unit
) {
    val amountInputState: MutableState<String> = rememberSaveable { 
        mutableStateOf(initialAmount) 
    }

    // 仅当外部金额(Summary页修改后)与当前输入状态不同时,同步输入框
    LaunchedEffect(initialAmount) {
        if (amountInputState.value != initialAmount) {
            amountInputState.value = initialAmount
        }
    }

    Column {
         AmountInputView(
            amountInput = amountInputState.value,
            onAmountChange = { amountInput ->
                amountInputState.value = amountInput
            }
        )

        Button(onClick = { onAmountConfirmed(amountInputState.value) }) {
            Text(text = "Continue")
        }
    }
}
  • 配置变更时:rememberSaveable保留输入状态,initialAmount与输入状态一致,LaunchedEffect不会执行赋值,避免内容丢失;
  • 从Summary页返回时:initialAmount已被修改,与输入状态不一致,LaunchedEffect同步最新金额到输入框。

方案二:基于MutableStateFlow的实现

若选择用Flow管理状态,可让ViewModel持有可观察的状态流,页面通过收集状态自动响应变化,同时满足页面不依赖ViewModel的要求。

1. 修改ViewModel为Flow实现

internal class PaymentFlowViewModel : ViewModel() {
    private val _amount = MutableStateFlow("")
    val amount = _amount.asStateFlow()

    fun updateAmount(newAmount: String) {
        _amount.value = newAmount
    }
}

2. 调整导航代码

在导航层收集Flow状态,传递给页面:

@Composable
internal fun NavigationGraph(viewModel: PaymentFlowViewModel = viewModel()) {
    val navController = rememberNavController()
    val currentAmount by viewModel.amount.collectAsState()

    NavHost(
        navController = navController,
        startDestination = "AMOUNT_INPUT_SCREEN"
    ) {
        composable("AMOUNT_INPUT_SCREEN") {
            AmountInputRoute(
                currentAmount = currentAmount,
                onAmountConfirmed = {
                    viewModel.updateAmount(it)
                    navController.navigate("SUMMARY_SCREEN")
                }
            )
        }
        composable("SUMMARY_SCREEN") {
            SummaryRoute(
                currentAmount = currentAmount,
                onAmountChanged = {
                    viewModel.updateAmount(it)
                }
            )
        }
    }
}

3. 修改AmountInputRoute

与方案一逻辑一致,监听currentAmount的变化并同步:

@Composable
internal fun AmountInputRoute(
    currentAmount: String,
    onAmountConfirmed: (String) -> Unit
) {
    val amountInputState: MutableState<String> = rememberSaveable { 
        mutableStateOf(currentAmount) 
    }

    LaunchedEffect(currentAmount) {
        if (amountInputState.value != currentAmount) {
            amountInputState.value = currentAmount
        }
    }

    Column {
         AmountInputView(
            amountInput = amountInputState.value,
            onAmountChange = { amountInput ->
                amountInputState.value = amountInput
            }
        )

        Button(onClick = { onAmountConfirmed(amountInputState.value) }) {
            Text(text = "Continue")
        }
    }
}

此方案的优势是状态变更可观察,ViewModel的状态管理更规范,适合复杂场景下的状态同步。


内容的提问来源于stack exchange,提问作者Benjamin Mesing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:55:19