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

Flutter中TextFormField的GeoJSON异步验证异常处理问题

问题分析与解决方案

核心问题

你的代码存在三个关键问题导致验证逻辑失效:

  1. 同步Validator无法等待异步操作:TextFormField的validator是同步回调,调用异步的checkGeoJson时,代码会直接跳过等待执行后续判断,此时parseSuccessful仍为初始值11,导致错误返回"Valid JSON"。
  2. 值传递无法修改外部变量:int是值类型,checkGeoJson函数中修改check变量不会影响外部的parseSuccessful,因为传递的是副本。
  3. 异常未被正确捕获: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:20:57