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

Flutter中Provider无法刷新DropdownMenu列表的问题排查

问题:Provider加载数据后DropdownMenu无法显示列表项

通过个人API获取数据连接正常,将返回数据存入Provider后,调用该Provider的数据填充DropdownMenu时,即便调试确认数据已加载完成,列表项仍无法显示。

相关代码

调用Provider的Widget代码

Column(
  children: [
    Container(
      color: Colors.green,
      child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              margin: const EdgeInsets.only(top: 20, bottom: 20),
              height: 10,
              width: 100,
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(10),
                  color: Colors.grey),
            )
          ]),
    ),
    IconList(
      labelText: 'Landmarks',
      icon: Icons.panorama_horizontal_outlined,
      items: context.watch<Landmarks>().getLandmarksNameList(), // 调用Provider
    ),
    const IconInput(
        labelText: '1', icon: Icons.addchart_outlined),
    const IconInput(
        labelText: '1', icon: Icons.addchart_outlined),
    ListView.builder(
      physics: const NeverScrollableScrollPhysics(),
      shrinkWrap: true,
      itemCount: 2,
      itemBuilder: (BuildContext context, int index) {
        return UserCard(user: usersList[index]);
      },
    ),
  ],
),

包含DropdownMenu的IconList组件代码

import 'package:flutter/material.dart';

class IconList extends StatefulWidget {
  final String labelText;
  final IconData icon;
  final List<String> items = [];

  IconList({super.key, required this.labelText, required this.icon, items});

  @override
  State<IconList> createState() => _IconListState();
}

class _IconListState extends State<IconList> {
  @override
  Widget build(BuildContext context) {
    String selectedItem = '';
    if (widget.items.isNotEmpty) {
      selectedItem = widget.items.first;
    }
    return Container(
      margin: const EdgeInsets.all(10.0),
      child: Row(
        children: [
          Icon(widget.icon),
          DropdownButton<String>(
            value: selectedItem,
            items: widget.items.map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
            onChanged: (String? value) {
              setState(() {
                selectedItem = value!;
              });
            },
          ),
        ],
      ),
    );
  }
}

Landmarks Provider代码

class Landmarks with ChangeNotifier {
  final List<Landmark> _items = [];

  List<Landmark> get landmarks => _items;

  void addLandmarks(List<Landmark> value) {
    _items.addAll(value);
    notifyListeners();
  }

  List<String> getLandmarksNameList() {
    List<String> list = [];
    print(_items.length);
    for (int i = 0; i < _items.length; i++) {
      list.add(_items[i].name);
    }
    return list;
  }
}

问题原因及修复方案

1. IconList未正确接收传入的items参数

当前IconList类中,items字段默认初始化了空列表,且构造函数未将传入的参数赋值给这个字段,导致Provider传递过来的数据根本没进入widget.items,DropdownButton自然拿不到数据。

修复:
修改IconList的字段定义和构造函数,确保传入的items被正确接收:

class IconList extends StatefulWidget {
  final String labelText;
  final IconData icon;
  final List<String> items; // 去掉默认空列表,改为必填字段

  // 构造函数中添加required修饰items,并赋值给类字段
  IconList({super.key, required this.labelText, required this.icon, required this.items});

  @override
  State<IconList> createState() => _IconListState();
}

2. selectedItem定义在build方法内导致状态异常

每次Widget重建时,build方法都会重新执行,定义在里面的selectedItem会被重置,不仅导致选中状态丢失,还可能在数据更新时无法正确同步。

修复:
将selectedItem移到State类中作为成员变量,并在initState中初始化:

class _IconListState extends State<IconList> {
  late String selectedItem;

  @override
  void initState() {
    super.initState();
    // 初始化选中项
    selectedItem = widget.items.isNotEmpty ? widget.items.first : '';
  }

  // 监听widget.items变化,更新选中项(防止外部数据更新时选中项失效)
  @override
  void didUpdateWidget(covariant IconList oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.items != widget.items) {
      setState(() {
        selectedItem = widget.items.isNotEmpty ? widget.items.first : '';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.all(10.0),
      child: Row(
        children: [
          Icon(widget.icon),
          DropdownButton<String>(
            value: selectedItem.isEmpty ? null : selectedItem, // 为空时设为null避免报错
            items: widget.items.map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
            onChanged: (String? value) {
              setState(() {
                selectedItem = value!;
              });
            },
          ),
        ],
      ),
    );
  }
}

额外注意点

  • 确保调用addLandmarks方法是在API数据获取完成后执行,且notifyListeners()已正确触发(调试确认数据已加载,这一步应该没问题)。
  • 当widget.items为空时,DropdownButton的value设为null,避免因空字符串导致的异常。

内容的提问来源于stack exchange,提问作者César Sotillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:30:50