Flutter开发计算器应用时setState不生效,求帮忙排查问题
问题核心原因
所有需要持久化的状态变量都被定义在build方法内部,每次调用setState触发组件重绘时,build方法都会重新执行,已修改的变量会被初始值直接覆盖,因此看起来setState没有生效。
修复方案
将状态变量移动到_MyAppState类内部、build方法外部即可,调整后的完整代码如下:
// ignore_for_file: avoid_types_as_parameter_names, non_constant_identifier_names, prefer_const_constructors, prefer_const_literals_to_create_immutables import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 状态变量移到build方法外部 String init = '0'; var res = ''; var operationToPerform = '0'; var firstNum = 0; var secondNum = 0; @override Widget build(BuildContext context) { _Calc(var got) { if (got == 'AC') { init = '0'; res = '0'; firstNum = 0; operationToPerform = '0'; secondNum = 0; } else if (got == 'C') { firstNum = 0; secondNum = 0; // 补充C按钮清空显示的逻辑 init = '0'; res = '0'; } else if (got == '+' || got == '-' || got == '/' || got == '*' || got == '%') { firstNum = int.parse(init); res = ''; operationToPerform = got; } else if (got == '=') { secondNum = int.parse(init); if (operationToPerform == '+') { res = (firstNum + secondNum).toString(); } if (operationToPerform == '-') { res = (firstNum - secondNum).toString(); } if (operationToPerform == '*') { res = (firstNum * secondNum).toString(); } if (operationToPerform == '/') { res = (firstNum / secondNum).toString(); } if (operationToPerform == '%') { res = ((firstNum / secondNum) * 100).toString(); } } else { res = int.parse(init + got).toString(); } setState(() { init = res; }); } Widget Numbutton(var num, [var color = Colors.black, var text]) { return Container( decoration: BoxDecoration(boxShadow: [ BoxShadow( color: Colors.grey.shade900, offset: Offset(2, 2), blurRadius: 15, spreadRadius: 1, ), BoxShadow( color: Colors.grey.shade700, offset: Offset(2, 2), blurRadius: 15, spreadRadius: 1, ) ], shape: BoxShape.circle), child: ElevatedButton( onPressed: () { _Calc(num); }, child: Text( num, style: TextStyle( fontSize: 25, fontWeight: FontWeight.w300, color: text, ), ), style: ElevatedButton.styleFrom( shape: CircleBorder(), primary: color, fixedSize: Size(40, 40)), ), ); } Widget OpButton(var text) { return ElevatedButton( onPressed: () { _Calc(text); }, child: Text( text, style: TextStyle(fontSize: 15, fontWeight: FontWeight.w400), ), style: ElevatedButton.styleFrom( primary: Colors.grey.shade900, ), ); } return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( backgroundColor: Colors.black, body: Wrap( direction: Axis.horizontal, alignment: WrapAlignment.spaceEvenly, children: <Widget>[ Column( children: <Widget>[ SizedBox( height: 220, ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( init, style: TextStyle( color: Colors.grey.shade500, ), ) ], ), SizedBox( height: 10, ), Row( mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ Text( init, style: TextStyle(color: Colors.grey.shade400, fontSize: 50), ), ], ), SizedBox( height: 50, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ OpButton('AC'), OpButton('C'), Numbutton('<', Colors.grey.shade300, Colors.grey.shade900), Numbutton('%', Colors.grey.shade300, Colors.grey.shade900), ], ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Numbutton('7'), Numbutton('8'), Numbutton('9'), Numbutton( '*', Colors.grey.shade300, Colors.grey.shade900, ), ], ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Numbutton('4'), Numbutton('5'), Numbutton('6'), Numbutton( '+', Colors.grey.shade300, Colors.grey.shade900), ]), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Numbutton('1'), Numbutton('2'), Numbutton('3'), Numbutton( '-', Colors.grey.shade300, Colors.grey.shade900), ]), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Numbutton('00'), Numbutton('0'), Numbutton('.'), Numbutton( '/', Colors.grey.shade300, Colors.grey.shade900), ]) ], ) ], ), floatingActionButton: FloatingActionButton( onPressed: () { _Calc('='); }, child: Icon(Icons.arrow_forward_ios_rounded), backgroundColor: Colors.grey.shade900, ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, ), ); } }
补充优化建议
- 目前点击小数点会触发类型转换错误,可后续补充小数输入的判断逻辑
- 除法运算返回结果为double类型,直接转字符串会带
.0后缀,可根据需求做格式化处理 - 退格键
<目前没有对应处理逻辑,可自行补充
内容的提问来源于stack exchange,提问作者myself_rana.raj
相关产品推荐
相关产品推荐

