API返回数据后DropdownButtonFormField2的UI未更新问题求助
核心问题
你的页面没有监听MobX中obsItemSpec的状态变化,虽然在API请求完成后调用了setState(),但这只是一次性触发重建,无法响应MobX状态的后续更新;切换页面再返回能刷新,是因为页面重新执行build方法时才读取到最新的obsItemSpec数据。
解决方案
1. 用MobX的Observer组件包裹下拉框
Observer会自动监听其builder函数内用到的Observable变量,当变量变化时自动重建内部Widget,无需手动调用setState()。
2. 优化Store中的Observable定义(可选但推荐)
将Observable<List<ItemSpec>?>改为ObservableList<ItemSpec>?,MobX的ObservableList对列表的增删改操作有更细粒度的监听支持,比普通的Observable<List>更适配列表场景。
修改后的代码
my_store.dart
part 'my_store.g.dart'; class MyStore = _MyStore with _$MyStore; abstract class _MyStore with Store { @observable ObservableList<ItemSpec>? obsItemSpec; @action Future getItemList() async { final itemList = await _useCase.getItemList(); obsItemSpec = ObservableList.of( itemList.map((list) => ItemSpec(list.name, list.id)).toList() ); } }
my_screen.dart
class MyScreenState extends State<MyScreen> { @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async => false, child: Scaffold( key: _scaffoldKey, // 用Observer包裹下拉框,监听MobX状态变化 body: Observer( builder: (_) => _buildItemDropDown(), ), ), ); } @override void initState() { super.initState(); // 直接调用API,无需手动setState _my_store.getItemList(); } Widget _buildItemDropDown() { // 处理数据未加载完成的情况 if (_my_store.obsItemSpec == null) { return const Center(child: CircularProgressIndicator()); } return DropdownButtonHideUnderline( key: UniqueKey(), child: DropdownButtonFormField2( decoration: InputDecoration( isDense: true, contentPadding: EdgeInsets.zero, border: OutlineInputBorder( borderRadius: BorderRadius.circular(4), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: ColorPalette.green[400]!)), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: ColorPalette.black[200]!)), ), isExpanded: true, hint: const Text( 'Options', style: TextStyle(fontSize: 14), ), iconOnClick: SvgPicture.asset( 'assets/svg/arrow_drop_down_activated.svg', ), icon: SvgPicture.asset( 'assets/svg/arrow_drop_down.svg', ), iconSize: 30, isDense: true, buttonHeight: 40, buttonPadding: const EdgeInsets.only(left: 12, right: 12), dropdownDecoration: BoxDecoration( borderRadius: BorderRadius.circular(4), ), items: _my_store.obsItemSpec!.asMap().entries.map((item) { return DropdownMenuItem<String>( value: item.value, enabled: false, child: StatefulBuilder( builder: (context, menuSetState) { final _isSelected = selectedItems.contains(item.value); return InkWell( onTap: () { _isSelected ? selectedItems.remove(item.value) : selectedItems.add(item.value); setState(() {}); menuSetState(() {}); }, child: Container( color: (item.key % 2 != 0) ? ColorPalette.white[400] : ColorPalette.white[500], height: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 18.0, vertical: 0), child: Row( children: [ _isSelected ? SvgPicture.asset( 'assets/svg/checkbox_green_outlined.svg', ) : SvgPicture.asset( 'assets/svg/checkbox_outlined_blank.svg', ), const SizedBox(width: 10), Text( item.value, style: const TextStyle( fontSize: 14, ), ), ], ), ), ); }, ), ); }).toList(), itemPadding: EdgeInsets.zero, value: selectedItems.isEmpty ? null : selectedItems.last, validator: (value) { if (value == null) { return 'Please select gender.'; } }, onChanged: (value) {}, selectedItemBuilder: (context) { return _my_store.obsItemSpec!.map( (item) { return Container( padding: const EdgeInsets.symmetric(horizontal: 0.0), child: Text( selectedItems.join(', '), style: const TextStyle( fontSize: 14, overflow: TextOverflow.ellipsis, ), maxLines: 1, ), ); }, ).toList(); }, ), ); } }
关键说明
Observer是MobX的核心组件,用于监听Observable变量变化,确保UI与状态同步。- 移除
initState中getItemList()后的setState(),Observer会自动处理状态更新后的UI重建。 - 添加数据加载状态判断,避免
obsItemSpec为null时出现空指针异常。
内容的提问来源于stack exchange,提问作者Webster
相关产品推荐
相关产品推荐

