Flutter中TextFormField的GeoJSON异步验证异常处理问题
问题分析与解决方案
核心问题
你的代码存在三个关键问题导致验证逻辑失效:
- 同步Validator无法等待异步操作:
TextFormField的validator是同步回调,调用异步的checkGeoJson时,代码会直接跳过等待执行后续判断,此时parseSuccessful仍为初始值11,导致错误返回"Valid JSON"。 - 值传递无法修改外部变量:
int是值类型,checkGeoJson函数中修改check变量不会影响外部的parseSuccessful,因为传递的是副本。 - 异常未被正确捕获:
geojson包的featuresFromGeoJson在隔离线程(Isolate)中运行,抛出的ParseErrorException未被你的try/catch正确捕获。
解决方案
由于默认TextFormField的validator不支持异步操作,我们需要通过状态管理+异步验证函数来实现需求:
1. 编写异步验证函数
返回Future<String?>,明确处理三种场景并捕获特定异常:
import 'package:geojson/geojson.dart'; import 'package:flutter/material.dart'; Future<String?> validateGeoJson(String? input) async { // 场景1:未输入任何文本 if (input == null || input.isEmpty) { return 'Please enter some text'; } try { // 解析GeoJSON,同时捕获隔离线程抛出的异常 await featuresFromGeoJson(input); // 可选:额外验证是否为LineString类型(如果需要严格匹配GeoJsonLine) // final geoJson = await GeoJson.parse(input); // if (geoJson.type != GeoJsonType.lineString) { // return 'GeoJSON must be a LineString'; // } // 场景3:有效GeoJSON return null; // 验证通过返回null } on ParseErrorException catch (e) { // 场景2:无法解析为GeoJSON print('GeoJSON解析错误: $e'); return 'Text is not valid GeoJSON'; } catch (e) { print('其他错误: $e'); return 'Invalid input'; } }
2. 用StatefulWidget管理验证状态
通过状态变量存储错误信息,在异步验证完成后更新UI:
class GeoJsonInput extends StatefulWidget { const GeoJsonInput({super.key}); @override State<GeoJsonInput> createState() => _GeoJsonInputState(); } class _GeoJsonInputState extends State<GeoJsonInput> { final TextEditingController trackController = TextEditingController(); final GlobalKey<FormState> formKey = GlobalKey<FormState>(); String? _validationError; Timer? _debounceTimer; // 实时验证防抖(可选,避免输入时频繁触发解析) void _onTextChanged(String value) { _debounceTimer?.cancel(); _debounceTimer = const Duration(milliseconds: 500).timer(() async { final error = await validateGeoJson(value); setState(() => _validationError = error); }); } // 提交时验证 Future<void> _submitForm() async { if (formKey.currentState!.validate()) { final error = await validateGeoJson(trackController.text); setState(() => _validationError = error); if (_validationError == null) { // 验证通过,执行保存GeoJsonLine的逻辑 print('GeoJSON验证通过,开始保存'); } } } @override void dispose() { trackController.dispose(); _debounceTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Form( key: formKey, child: Column( children: [ TextFormField( controller: trackController, decoration: InputDecoration( labelText: 'Enter GeoJSON', errorText: _validationError, ), // 同步验证仅做非空检查,异步验证处理GeoJSON解析 validator: (value) => value?.isEmpty ?? true ? 'Please enter some text' : null, onChanged: _onTextChanged, maxLines: 5, ), const SizedBox(height: 16), ElevatedButton( onPressed: _submitForm, child: const Text('Submit'), ), ], ), ); } }
关键细节说明
- 异步验证与状态更新:通过
setState更新错误信息,确保UI能实时反映验证结果。 - 防抖处理:在
onChanged中添加防抖,避免用户输入过程中频繁触发GeoJSON解析,提升性能。 - 异常捕获:明确捕获
ParseErrorException,确保隔离线程中抛出的解析错误能被正确处理。
内容的提问来源于stack exchange,提问作者Isaac
相关产品推荐
相关产品推荐

