Jetpack Compose中TextField与SQL结合:加载后无法输入问题求助
我尝试将多个TextField的数据保存到SQL数据库,重启应用时再加载回TextField。目前保存和加载功能可正常实现,但加载数据后用户无法在TextField中输入新内容,推测该问题与状态管理有关,请求排查思路。
补充说明:问题出在callData()与TextField的结合上,不调用callData()时TextField可正常输入,无Compose的TextField时应用也能正常运行。
原代码
class MainActivity : ComponentActivity() { val context = this var db = DataBaseHandler(context) var initialload : Boolean = true var name = " " var number = " " override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) callData() setContent { BackgroundLocationTrackingTheme { Column( modifier = Modifier.fillMaxSize() .padding(32.dp) .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top ) { // var name by rememberSaveable { mutableStateOf("") } TextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) Spacer(modifier = Modifier.height(16.dp)) // var number by rememberSaveable { mutableStateOf("") } TextField( value = number, onValueChange = { number = it }, label = { Text("Your phone number") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) ) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { if(name.toString().length > 0 && number.toString().length > 0) { var user = User(name.toString(),number.toString().toInt()) db.insertData(user) } else{ Toast.makeText(context, "Please fill in all data", Toast.LENGTH_SHORT).show() } }) { Text(text = "Save") } } } } // callData() } fun callData(){ // Toast.makeText(context, initialload, Toast.LENGTH_SHORT).show() if(initialload == true) { var data = db.readData() dataname = data.get(0).name.toString() datanumber = data.get(0).number.toString() initialload = false // Toast.makeText(context, "initialload is false", Toast.LENGTH_SHORT).show() } else {} } }
核心问题:状态未被Compose追踪
你在Activity中定义的name和number是普通变量,不属于Compose的State类型。Compose仅会在State变量变化时触发UI重组,修改普通变量无法通知Compose更新UI,导致输入内容无法在TextField中显示。具体修复步骤
替换为Compose State变量
在setContent的Composable代码块内,用rememberSaveable定义可持久化的状态变量,替代Activity中的普通变量:var name by rememberSaveable { mutableStateOf("") } var number by rememberSaveable { mutableStateOf("") }这样Compose会自动追踪变量变化,每次输入修改都会触发TextField的UI更新。
正确加载初始数据
不要在onCreate中直接调用callData()修改普通变量,改用LaunchedEffect在Composable首次启动时加载数据,确保只执行一次:LaunchedEffect(Unit) { if (initialload) { val data = db.readData() name = data[0].name.toString() number = data[0].number.toString() initialload = false } }调整变量作用域
删除Activity中的name、number普通变量,将状态变量的作用域限制在Composable内部,符合Compose状态管理的最佳实践。
修改后的完整代码
class MainActivity : ComponentActivity() { val context = this var db = DataBaseHandler(context) var initialload: Boolean = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { BackgroundLocationTrackingTheme { var name by rememberSaveable { mutableStateOf("") } var number by rememberSaveable { mutableStateOf("") } // 加载初始数据库数据 LaunchedEffect(Unit) { if (initialload) { val data = db.readData() name = data[0].name.toString() number = data[0].number.toString() initialload = false } } Column( modifier = Modifier.fillMaxSize() .padding(32.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top ) { TextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) Spacer(modifier = Modifier.height(16.dp)) TextField( value = number, onValueChange = { number = it }, label = { Text("Your phone number") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) ) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { if (name.isNotEmpty() && number.isNotEmpty()) { val user = User(name, number.toInt()) db.insertData(user) } else { Toast.makeText(context, "Please fill in all data", Toast.LENGTH_SHORT).show() } }) { Text(text = "Save") } } } } } }
内容的提问来源于stack exchange,提问作者Qualla

