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

Compose OutlinedTextField输入无响应 requestCursorUpdates错误修复

问题现象

在ViewModel中使用Data Class作为状态持有类时,页面内多个OutlinedTextField输入框输入内容无任何响应。每次通过软键盘输入字符时,Logcat输出如下Debug级警告日志,但不会抛出运行时异常:

W/RecordingIC: requestCursorUpdates is not supported

涉及原有代码如下:

状态数据类定义

data class ShoppingListItemState(
  val name: String = "",
  val category: String = "",
  val quantity: String = "",
  val unit: String = "",
  val ppu: String = "",
  val notes: String = "",
  val hasImage: Boolean = false,
  val imageUri: Uri? = null 
)

原有ViewModel实现

class ShoppingListScreenViewModel(): ViewModel() {

    val shoppingListItemState = mutableStateOf(ShoppingListItemState())

    fun setListItemStateValue(stateToEdit: String, stateValue: String) {
      val item = shoppingListItemState.value
      when (stateToEdit) {
          "Name" -> item.copy(name = stateValue)
          "Category" -> item.copy(category = stateValue)
          "Quantity" -> item.copy(quantity = stateValue)
          "Unit" -> item.copy(unit = stateValue)
          "PPU" -> item.copy(ppu = stateValue)
          "Notes" -> item.copy(notes = stateValue)
          "HasImage" -> item.copy(hasImage =stateValue.toBoolean())
          "ImageUri" -> item.copy(imageUri = stateValue.toUri())
      }
      shoppingListItemState.value = item 
   }
}

输入框调用代码

val shoppingListScreenViewModel: ShoppingListScreenViewModel = viewModel()
           
CustomOutlinedTextField(
        modifier = Modifier
            .fillMaxWidth()
            .onPreviewKeyEvent {
                if (it.key == Key.Tab) {
                    focusManager.moveFocus(FocusDirection.Down)
                    true
                } else {
                    false
                }
            },
        label = stringResource(id = R.string.item_name),
        inputVal = shoppingListScreenViewModel.shoppingListItemState.value.name,
        isSingleLine = true,
        keyboardOptions = KeyboardOptions.Default.copy(
            capitalization = KeyboardCapitalization.Sentences,
            autoCorrect = false,
            keyboardType = KeyboardType.Text,
            imeAction = ImeAction.Next
        ),
        keyboardActions = KeyboardActions(
            onNext = { focusManager.moveFocus(FocusDirection.Down) }
        )
) { shoppingListScreenViewModel.setListItemStateValue("Name", it) }

自定义输入框实现

@Composable
fun CustomOutlinedTextField(
    modifier: Modifier = Modifier,
    label: String = "",
    inputVal: String,
    isSingleLine: Boolean = false,
    maxLines: Int = 0,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    onValChange: (String) -> Unit
) {
    OutlinedTextField(
        value = inputVal,
        onValueChange = { onValChange(it) },
        label = { Text(text = label) },
        singleLine = isSingleLine,
        maxLines = maxLines,
        keyboardOptions = keyboardOptions,
        keyboardActions = keyboardActions,
        modifier = modifier
    )
}
问题根因

输入无响应和日志中的requestCursorUpdates is not supported警告无关,该警告是部分厂商定制输入法对输入法框架接口的不兼容提示,不影响正常输入逻辑。
核心问题出在状态更新逻辑:Kotlin data class的copy()方法会生成属性更新后的全新对象实例,不会修改原有实例。原ViewModel代码中when分支调用copy()后没有接收返回的新对象,最后将未做任何修改的旧item实例重新赋值给状态,Compose无法检测到状态的实际变化,不会触发重组,输入框始终显示初始空字符串,表现为输入无响应。

修复方案

修改ViewModel中的状态更新逻辑,直接接收copy()返回的新状态实例赋值给状态变量,同时做基础的状态封装优化:

class ShoppingListScreenViewModel: ViewModel() {
    // 使用by委托简化状态访问,private set禁止外部直接修改状态
    var shoppingListItemState by mutableStateOf(ShoppingListItemState())
        private set

    fun setListItemStateValue(stateToEdit: String, stateValue: String) {
        // 直接将copy生成的新实例赋值给状态,确保状态引用更新触发重组
        shoppingListItemState = when (stateToEdit) {
            "Name" -> shoppingListItemState.copy(name = stateValue)
            "Category" -> shoppingListItemState.copy(category = stateValue)
            "Quantity" -> shoppingListItemState.copy(quantity = stateValue)
            "Unit" -> shoppingListItemState.copy(unit = stateValue)
            "PPU" -> shoppingListItemState.copy(ppu = stateValue)
            "Notes" -> shoppingListItemState.copy(notes = stateValue)
            "HasImage" -> shoppingListItemState.copy(hasImage = stateValue.toBoolean())
            "ImageUri" -> shoppingListItemState.copy(imageUri = stateValue.toUri())
            // 补充else分支避免分支遗漏导致状态异常
            else -> shoppingListItemState
        }
    }
}

修改完成后状态可正常更新,输入框输入会实时响应。

内容的提问来源于stack exchange,提问作者Raj Narayanan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:03:28