Flutter setState失效及InputConnection报错:BMI应用输入无法更新变量
解决BMI应用的变量更新问题与输入连接警告
核心问题分析
你遇到的height和weight变量无法更新的问题,主要源于两个关键错误:
- 字符串转数值的方式错误:
onSubmitted接收的参数是String类型,直接用as double强制转换完全无效,这种操作会在运行时触发隐性错误,导致变量赋值失败。 - setState中的错误写法:在weight的输入回调里,你写了
return weight=input2 as double;——setState的回调是void类型,return语句会提前终止执行,再加上错误的类型转换,自然没法正确更新变量。
至于日志里的IInputConnectionWrapper警告,大多是输入框在状态变化时的临时连接失效导致的,解决核心变量更新问题后,这类警告通常会随之缓解。
修复后的完整代码
主页面代码
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'calculation.dart'; void main() => runApp(MyApp()); /// This is the main application widget. class MyApp extends StatelessWidget { static const String _title = 'BMI'; @override Widget build(BuildContext context) { return MaterialApp( title: _title, home: Scaffold( appBar: AppBar(title: const Text(_title), centerTitle: true, backgroundColor: Colors.amber[900], ), body: Center( child: MyStatefulWidget(), ), ), ); } } enum SingingCharacter { lafayette, jefferson } /// This is the stateful widget that the main application instantiates. class MyStatefulWidget extends StatefulWidget { MyStatefulWidget({Key? key}) : super(key: key); @override _MyStatefulWidgetState createState() => _MyStatefulWidgetState(); } /// This is the private State class that goes with MyStatefulWidget. class _MyStatefulWidgetState extends State<MyStatefulWidget> { SingingCharacter _character = SingingCharacter.lafayette; double height = 1; double weight = 1; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(10.0), child: Scrollbar( child: SingleChildScrollView( child: Card( color: Colors.amber[50], child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.fromLTRB(0, 30, 10, 10), child: Text("Sex:", style: TextStyle(fontSize: 24, letterSpacing: 1.0)), ), ListTile( title: const Text('Female', style: TextStyle(fontSize: 18, letterSpacing: 1.0) ), leading: Radio( activeColor: Colors.orange, value: SingingCharacter.lafayette, groupValue: _character, onChanged: (SingingCharacter? value) { if (value != null) { setState(() { _character = value; }); } }, ), ), ListTile( title: const Text('Male', style: TextStyle(fontSize: 18, letterSpacing: 1.0,) ), leading: Radio( activeColor: Colors.orange, value: SingingCharacter.jefferson, groupValue: _character, onChanged: (SingingCharacter? value) { if (value != null) { setState(() { _character = value; }); } }, ), ), SizedBox(height: 10.0), Text("Your height:", style: TextStyle(fontSize: 24, letterSpacing: 1.0) ), SizedBox(height: 10), Padding( padding: const EdgeInsets.fromLTRB(30, 0, 50, 10), child: TextField( decoration: new InputDecoration(labelText: "Your height(cm)"), keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], // Only numbers can be entered onSubmitted: (input1){ // 用tryParse安全转换,避免无效输入崩溃 final inputHeight = double.tryParse(input1); if(inputHeight != null && inputHeight > 0){ setState(() => height = inputHeight); print(inputHeight); } }, ), ), SizedBox(height: 20), Text("Your weight:", style: TextStyle(fontSize: 24, letterSpacing: 1.0) ), SizedBox(height: 10), Padding( padding: const EdgeInsets.fromLTRB(30, 0, 50, 10), child: new TextField( decoration: new InputDecoration(labelText: "Your weight(kg)"), keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], // Only numbers can be entered onSubmitted: (input2){ final inputWeight = double.tryParse(input2); if (inputWeight != null && inputWeight > 0){ setState(() { weight = inputWeight; }); } }, ),), SizedBox(height: 10,), RaisedButton( padding: EdgeInsets.fromLTRB(20, 5, 20, 5), onPressed: (){ // 完善按钮逻辑:计算并触发结果判断 final bmiValue = Calculation(height, weight); Results(bmiValue); }, color: Colors.amber[900], child: Text( 'Calculate', style: TextStyle( color: Colors.white, fontSize: 30, letterSpacing: 2.0, ), ), ), SizedBox(height: 20,), Text('Results: $height cm, $weight kg'), ], ), ), ), ), ); } }
计算函数代码
import 'dart:math'; // 修改为返回BMI计算值,同时修正公式逻辑 double Calculation(double height, double weight){ // 正确BMI公式:体重(kg) / (身高(m))²,需把厘米转米 double heightInM = height / 100; double value = weight / pow(heightInM, 2); print(value); return value; } void Results(double value){ if(value < 18.5){ print("kilonuz ideal kilonuzdan az."); } else if(value > 25){ if(value > 30){ print("kilonuz ideal kilonuzun çok üstünde, sağlığınız risk altında."); } else{ print("kilonuz ideal kilonuzdan fazla."); } } else{ print("ideal kilonuzdasınız."); } }
额外优化说明
- BMI公式修正:原来的公式写反了,已经调整为符合国际标准的计算逻辑,同时增加了厘米到米的转换。
- 空安全处理:对Radio的回调参数做了空判断,适配Flutter的空安全规范。
- 安全类型转换:用
double.tryParse替代强制转换,避免用户输入无效内容导致应用崩溃。 - 按钮逻辑完善:原来的按钮仅返回函数,现在改为完整调用计算+结果判断流程,实现了预期的功能。
内容的提问来源于stack exchange,提问作者elfythepinky
相关产品推荐
相关产品推荐

