Flutter setState 不更新特定的小部件

Flutter setState not updating a particular widget

我正在使用 multi_select_flutter 在我的 flutter 项目中显示多芯片。但是,我试图在用户搜索时使用从我的 api 加载的数据向芯片添加更多项目,但它不会更新多芯片小部件的状态。这是我的完整代码。

即使我热重载,它也不会自行更新。我可以手动执行刷新更新的唯一方法是重新加载小部件并连续重新加载。关于为什么会发生这种奇怪行为的任何信息?

class MultiChoiceComponent extends StatefulWidget {
  const MultiChoiceComponent({Key key}) : super(key: key);

  @override
  _MultiChoiceComponentState createState() => _MultiChoiceComponentState();
}

class _MultiChoiceComponentState extends State<MultiChoiceComponent> {
  ApiMethods apiMethods;

  TextEditingController searchController = TextEditingController();
  List<MultiSelectItem<dynamic>> labels = [];
  final TextEditingController textEditingController = TextEditingController();
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    apiMethods = new ApiMethods(context: context);
  }
  @override
  Widget build(BuildContext context) {
    return ListView(
      shrinkWrap: true,
      children: [
        Container(
          padding: EdgeInsets.symmetric(horizontal: 16),
          child: Text(
            'Search and select as many symptoms been experienced, it helps with a more accurate diagnosis',
            textAlign: TextAlign.start,
            style: TextStyle(
              fontSize: 14,
              height: 1.8,
              fontWeight: FontWeight.w400,
              fontFamily: 'Euclid',
              color: AppColors.grey1,
            ),
          ),
        ),
        SizedBox(
          height: 20,
        ),
        Container(
          padding: EdgeInsets.symmetric(horizontal: 16,),
          // height: maxLines * 50.0,
          child: TextField(
            controller: textEditingController,
            cursorColor: Colors.black26,
            onChanged: (val){
              if(val!=""){
                searchSymptoms(val);
              }
            },
            decoration: InputDecoration(
                filled: true,
                hintStyle: TextStyle(
                  fontSize: 14,
                  height: 1.6,
                  fontWeight: FontWeight.w400,
                  fontFamily: 'Euclid',
                  color: AppColors.grey1,
                ),
                hintText: "Search for a symptom/illness",
                fillColor: Colors.white,
                contentPadding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 14),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                ),
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                ),
                enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                )),
          ),
        ),
        MultiSelectChipField(
          scroll: false,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.transparent, width: 1.8),
          ),
          showHeader: false,
          selectedTextStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            fontFamily: 'Euclid',
            color: Colors.white,
          ),
          chipShape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(12),
            ),
          ),
          selectedChipColor: AppColors.customGreen,
          chipColor: Colors.white,
          textStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            fontFamily: 'Euclid',
            color: AppColors.textColor,
          ),
          items: labels,
          onTap: (value) {
            ///add symptoms to list
            print(value);
            selectedSymptoms = value as List<Conditions>;
          },
        ),
      ],
    );
  }
  Future<void> searchSymptoms(String searchQuery) async {
    List<dynamic> _data =  await apiMethods.searchConditions(symptomCheckerAge, searchQuery);
    conditions = Conditions.fromJsonList(_data);
    labels = conditions.map((e) => MultiSelectItem(e, e.label)).toList();
    setState(() {});
  }
}

试试这个

Future<void> searchSymptoms(String searchQuery) async {
    List<dynamic> _data =  await apiMethods.searchConditions(symptomCheckerAge, searchQuery);
      conditions = Conditions.fromJsonList(_data);
      labels = conditions.map((e) => MultiSelectItem(e, e.label)).toList();
    setState(() {});
}

你能分享完整的代码吗..比如你声明标签和条件等变量的部分。您需要首先确保这些变量不是 final 并且它们使用了 late 关键字或类似 List 的东西?标签。 如果还有其他问题,请分享这个有状态的整个代码 class

**编辑

所以我用自定义数据尝试了这个给定的 Chip Widget,它工作正常。这意味着我在按下时添加的项目正在添加到新列表中。看看并尝试一些更改,看看是否适合您

class _MyHomePageState extends State<MyHomePage> {
static List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
Animal(id: 11, name: "Cat"),
Animal(id: 12, name: "Fish"),
Animal(id: 13, name: "Rabbit"),
];
dynamic _items = _animals
  .map((animal) => MultiSelectItem<Animal>(animal, animal.name))
  .toList();
@override
Widget build(BuildContext context) {
return new Scaffold(
  backgroundColor: Colors.white,
  appBar: new AppBar(
    title: new Text('Hello'),
  ),
  body: ListView(
    scrollDirection: Axis.vertical,
    physics: NeverScrollableScrollPhysics(),
    children: [
      Container(
        child: MultiSelectChipField(
          scroll: false,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.transparent, width: 1.8),
          ),
          showHeader: false,
          selectedTextStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            color: Colors.blue,
          ),
          chipShape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(12),
            ),
          ),
          selectedChipColor: Colors.green,
          chipColor: Colors.yellow,
          textStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            color: Colors.black,
          ),
          items: _items,
          onTap: (value) {
            ///add symptoms to list
            print(value);
          },
        ),
      ),
      ElevatedButton(
          onPressed: () {
            _items.add(MultiSelectItem<Animal>(
                Animal(id: 27, name: 'name'), 'new'));
            setState(() {});
          },
          child: Text('Add'))
    ],
  ),
  );
 }
}

 class Animal {
  final int id;
  final String name;

Animal({
required this.id,
required this.name,
});

}

我也在为 MultiSelectChipField 的热重载而苦苦挣扎,解决方案是在重载期间更新 globalkey。

伪代码:

  late var _multiSelectKey;
  late List<MultiSelectItem<SomeClass?>>? _items;

  @override
  void initState() {
       _items = null;
  }
    
  void reloadChip()
  {
    _multiSelectKey = GlobalKey<FormFieldState>();
    _items = getItemsFromSomeWhere();
  }

脚手架芯片有这些参数

MultiSelectChipField<SomeClass?>(
                  initialValue: getSelected(),
                  key: _multiSelectKey,
                  title: const Text("Title"),
                  items: _items!,
                  onTap: (items) async { },
                  },
                ),

当调用函数 reloadChip() 并触发 setState(() {}); 时,MultiSelectChipField 将更新。