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
相关产品推荐
相关产品推荐

