Flutter页面加载前从SharedPreference读数据填充Dropdown失败如何解决
问题解决方法
问题根源
- 你的数据加载是异步操作,
read()方法执行完成后,你直接修改了dropDownItemValue、notePages这些状态变量,但没有调用setState()通知Flutter框架重新渲染组件,所以Dropdown控件始终用的是初始化时的空列表进行渲染,表现为无法点开、没有选项。 - 初始状态下
dropDownItemValue为空,你直接将selectedValue赋值为列表第一个元素,异步没完成时会出现值不匹配的异常,也会导致Dropdown功能异常。
修复方案
1. 异步操作完成后调用setState刷新UI
修改initState中的逻辑,所有状态修改操作都包裹在setState中,同时增加初始加载的判断逻辑,避免异步未完成时报错:
@override void initState() { super.initState(); // 先给下拉框设置初始默认值 dropDownItemValue = ['加载中...']; selectedValue = dropDownItemValue[0]; read().then((_) { // 先清空原有数据,避免多次调用时重复添加 notePages.clear(); dropDownItemValue.clear(); for (var i = 0; i < pages.length; i++) { notePages.add(pages[i]); } for (var i = 0; i < notePages.length; i++) { dropDownItemValue.add(notePages[i].pageName); } dropDownItemValue.add(''); dropDownItemValue.add('Add Page'); print(dropDownItemValue); // 状态修改完成后调用setState刷新UI setState(() { selectedValue = dropDownItemValue[0]; }); }); }
2. 优化冗余逻辑
你原来的read()方法中,每次循环添加page都调用addInTheList(),会导致notePages列表出现重复元素,可以调整为读取完全部数据后一次性添加:
Future<NotePages?> read() async { SharedPreferences prefs = await SharedPreferences.getInstance(); var keys = prefs.getKeys(); // 先清空原有pages数据,避免重复 pages.clear(); for (var key in keys) { var pageList = prefs.getStringList(key); if (pageList?[0] == 'page') { NotePages page = NotePages( type: pageList![0], pageName: pageList[1], createdTime: DateTime.parse(pageList[2])); pages.add(page); } } // 读取完全部数据后一次性添加到notePages addInTheList(); return null; }
额外注意事项
- 你需要保证Dropdown组件的
items属性生成的每一个DropdownMenuItem的value值和dropDownItemValue中的元素完全一致,避免出现selectedValue不在选项列表中的异常。 - 如果数据加载时间较长,可以在初始阶段给Dropdown加个禁用状态或者加载提示,提升用户体验。
内容的提问来源于stack exchange,提问作者can çağlar kırıcı
相关产品推荐
相关产品推荐

