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类型)。
修复步骤
- 在State类中添加变量存储加载完成的选项列表
- 在
initState中异步加载文件数据,通过setState更新状态 - 在
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
相关产品推荐
相关产品推荐

