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

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.");
  }
}

额外优化说明

  1. BMI公式修正:原来的公式写反了,已经调整为符合国际标准的计算逻辑,同时增加了厘米到米的转换。
  2. 空安全处理:对Radio的回调参数做了空判断,适配Flutter的空安全规范。
  3. 安全类型转换:用double.tryParse替代强制转换,避免用户输入无效内容导致应用崩溃。
  4. 按钮逻辑完善:原来的按钮仅返回函数,现在改为完整调用计算+结果判断流程,实现了预期的功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 13:23:21