Flutter中double.parse()报FormatException: Invalid double错误求助
问题排查:FormatException: Invalid double 解决方法
问题根源
- 字符串格式不兼容:
salePriceController.text存储的是带美元符号$和千位分隔符,的货币字符串(如$4,249,000.00),double.parse()只能解析纯数字格式的字符串,无法识别这些非数字符号,直接解析会抛出FormatException。 - 格式化方法逻辑错误:你的
_formatCurrency方法存在严重逻辑问题——不管输入的数值是什么,最终都返回"\$0.00",完全没有使用currencyFormatter.format(value)生成的正确格式化字符串,导致初始显示的售价永远为$0.00,和传入的salePrice不符。
修复方案
1. 修正_formatCurrency方法
修改方法逻辑,正确返回格式化后的货币字符串:
final NumberFormat currencyFormatter = NumberFormat.currency(symbol: '\$', decimalDigits: 2); String _formatCurrency(double value) { // 直接传入double类型数值,用NumberFormat格式化 return currencyFormatter.format(value); }
注意:将参数类型从
String改为double,因为初始化时传入的是widget.salePrice(double类型),无需先转字符串再处理。
2. 修复calculateCommission方法
在解析前先清理货币字符串中的非数字字符(保留小数点):
void calculateCommission() { if (salePriceController.text.isNotEmpty && commissionRateController.text.isNotEmpty) { try { // 清理售价字符串:移除$和逗号,只保留数字和小数点 String cleanedSalePrice = salePriceController.text.replaceAll(RegExp(r'[\$,]'), ''); double salePrice = double.parse(cleanedSalePrice); double commissionRate = double.parse(commissionRateController.text); double commissionAmount = (salePrice * commissionRate) / 100; setState(() { commission = commissionAmount; }); } catch (e) { print(e); // 可以在这里添加错误提示,比如显示SnackBar } } else { // 处理空字段,比如显示提示 } }
3. 修正initState初始化逻辑
因为_formatCurrency参数改为double类型,所以初始化时直接传入widget.salePrice:
@override void initState() { super.initState(); salePriceController.text = _formatCurrency(widget.salePrice); }
4. 可选:添加输入格式化(优化用户体验)
给售价TextField添加TextInputFormatter,限制用户只能输入数字和小数点,同时自动格式化货币:
TextField( controller: salePriceController, decoration: const InputDecoration(labelText: 'Sale Price (\$)'), keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')), // 可选:添加自动货币格式化的输入 formatter // CurrencyInputFormatter(symbol: '\$'), // 需自定义或使用第三方包 ], )
完整修正后的代码
class CommissionCalculatorPopup { static void showCommissionCalculator(BuildContext context, double salePrice) { showDialog( context: context, builder: (BuildContext context) { return CommissionCalculatorDialog(salePrice: salePrice); }, ); } } class CommissionCalculatorDialog extends StatefulWidget { final double salePrice; const CommissionCalculatorDialog({required this.salePrice, super.key}); @override State<CommissionCalculatorDialog> createState() => _CommissionCalculatorDialogState(); } class _CommissionCalculatorDialogState extends State<CommissionCalculatorDialog> { TextEditingController salePriceController = TextEditingController(); TextEditingController commissionRateController = TextEditingController(); double commission = 0.0; final NumberFormat currencyFormatter = NumberFormat.currency(symbol: '\$', decimalDigits: 2); String _formatCurrency(double value) { return currencyFormatter.format(value); } @override void initState() { super.initState(); salePriceController.text = _formatCurrency(widget.salePrice); } @override Widget build(BuildContext context) { return AlertDialog( title: Text( 'Commission Calculator', style: TextStyle(fontSize: 8.sp), ), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: salePriceController, decoration: const InputDecoration(labelText: 'Sale Price (\$)'), keyboardType: TextInputType.numberWithOptions(decimal: true), ), TextField( controller: commissionRateController, decoration: const InputDecoration(labelText: 'Commission Rate (%)'), keyboardType: TextInputType.numberWithOptions(decimal: true), ), SizedBox(height: 20.sp), ElevatedButton( onPressed: calculateCommission, child: const Text('Calculate Commission'), ), SizedBox(height: 20.sp), Text( 'Commission: \$${commission.toStringAsFixed(2)}', style: TextStyle(fontSize: 8.sp), ), ], ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('Close'), ), ], ); } void calculateCommission() { if (salePriceController.text.isNotEmpty && commissionRateController.text.isNotEmpty) { try { String cleanedSalePrice = salePriceController.text.replaceAll(RegExp(r'[\$,]'), ''); double salePrice = double.parse(cleanedSalePrice); double commissionRate = double.parse(commissionRateController.text); double commissionAmount = (salePrice * commissionRate) / 100; setState(() { commission = commissionAmount; }); } catch (e) { print(e); // 可添加错误提示,例如: // ScaffoldMessenger.of(context).showSnackBar( // SnackBar(content: Text('Invalid input: $e')), // ); } } else { // 处理空字段 // ScaffoldMessenger.of(context).showSnackBar( // const SnackBar(content: Text('Please fill all fields')), // ); } } }
内容的提问来源于stack exchange,提问作者LostTexan
相关产品推荐
相关产品推荐

