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

Flutter:从文本文件读取数据实现Autocomplete组件遇类型错误

问题:Flutter Autocomplete读取本地文本文件时的类型错误

尝试实现Flutter的Autocomplete组件,将选项数据存储在文本文件中,但读取文件时遇到错误:

A value of type 'Future<List?>' can't be assigned to a variable of type 'List?'

相关代码:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ContractControl extends StatefulWidget {
  const ContractControl({super.key});

  @override
  State<ContractControl> createState() => _ContractControlState();
}

class _ContractControlState extends State<ContractControl> {
  Future<List<String>?> getData() async {
    try {
      String fileData = await rootBundle.loadString('assets/instruments.txt');
      List<String> lines = fileData.split('\n');
      return lines;
    } catch (e) {
      throw (e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    List<String>? listItems = getData(); // 错误发生在这里
    return Scaffold(
      appBar: AppBar(title: const Text('Contract Control')),
      body: Autocomplete<String>(
        optionsBuilder: (TextEditingValue textEditingValue) {
          Future<List<String>?> listItems = getData();
          if (textEditingValue.text == '') {
            return const Iterable<String>.empty();
          }
          return listItems.where((String item) {
            return item.contains(textEditingValue.text.toUpperCase());
          });
        },
        onSelected: (String item) {
          print('Item selected');
        },
      ),
    );
  }
}

解决方案

错误原因

getData()是异步函数,返回的是Future<List<String>?>类型,而非直接的List<String>?。你不能直接将Future赋值给普通列表变量,也无法在optionsBuilder中对Future调用where方法(因为Future不是Iterable类型)。

修复步骤

  1. 在State类中添加变量存储加载完成的选项列表
  2. 在initState中异步加载文件数据,通过setState更新状态
  3. 在optionsBuilder中使用已加载的列表进行筛选

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ContractControl extends StatefulWidget {
  const ContractControl({super.key});

  @override
  State<ContractControl> createState() => _ContractControlState();
}

class _ContractControlState extends State<ContractControl> {
  List<String>? _listItems; // 存储加载后的选项数据

  @override
  void initState() {
    super.initState();
    _loadData(); // 页面初始化时加载文件
  }

  Future<void> _loadData() async {
    try {
      String fileData = await rootBundle.loadString('assets/instruments.txt');
      // 分割文本并过滤空行,避免无效选项
      List<String> lines = fileData.split('\n')
          .where((line) => line.trim().isNotEmpty)
          .toList();
      setState(() {
        _listItems = lines;
      });
    } catch (e) {
      debugPrint('加载文件失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Contract Control')),
      body: Autocomplete<String>(
        optionsBuilder: (TextEditingValue textEditingValue) {
          // 列表未加载完成时返回空选项
          if (_listItems == null) return const Iterable<String>.empty();
          
          final inputText = textEditingValue.text.toUpperCase();
          if (inputText.isEmpty) {
            return const Iterable<String>.empty();
          }
          // 使用已加载的列表进行筛选,支持不区分大小写匹配
          return _listItems!.where((String item) {
            return item.toUpperCase().contains(inputText);
          });
        },
        onSelected: (String item) {
          print('选中的选项: $item');
        },
      ),
    );
  }
}

关键说明

  • 通过initState异步加载数据,确保数据加载完成后更新UI,避免在build方法中处理异步操作
  • 过滤文本中的空行,避免出现无效的空选项
  • 在optionsBuilder中先判断列表是否已加载,防止空指针异常
  • 将输入文本和选项统一转为大写,实现不区分大小写的匹配(可根据需求调整为小写或保留原格式)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:41:11