英文:
How to fix _TypeError (type 'List<Animal?>' is not a subtype of type 'List<Animal>?' of 'value')
问题
无法理解我的代码有什么问题。无论我尝试什么,当尝试确认多选小部件中的选择时,我仍然会收到此错误。
这是我的代码。
```dart
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
  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"),
  ];
  final _items = _animals
      .map((animal) => MultiSelectItem<Animal>(animal, animal.name))
      .toList();
  List<Animal?>? _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>?>>(); // 在此处更新
  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField<Animal>(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: Text("Animals"),
        buttonText: Text("Favorite Animals"),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return "Required";
          }
          List<String> names = values.map((e) => e!.name).toList(); // 在此处更新
          if (names.contains("Frog")) {
            return "Frogs are weird!";
          }
          return null;
        },
        onConfirm: (List<Animal?>? values) { // 在此处更新
          setState(() {
            _selectedAnimals3 = values;
          });
          _multiSelectKey.currentState?.validate();
        },
        chipDisplay: MultiSelectChipDisplay(
          onTap: (item) {
            setState(() {
              _selectedAnimals3!.remove(item);
            });
            _multiSelectKey.currentState?.validate();
          },
        ),
      ),
    );
  }
}
我尝试将_selectedAnimals3和'values'都转换,并使用_animals进行初始化,但仍然出现相同的错误。我需要在确认时将_selectedAnimals3 填充为所选项。
<details>
<summary>英文:</summary>
I am unable to understand what's wrong with my code. Whatever I try I am still getting this error when trying to confirm my selection in multiselect widget.
Here's my code.
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
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"),
];
final _items = _animals
.map((animal) => MultiSelectItem<Animal>(animal, animal.name))
.toList();
List<Animal?>? _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>?>>(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: Text("Animals"),
buttonText: Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e!.name).toList(); // Update here
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal?>? values) { // Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3!.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
I tried to cast _selectedAnimals3 and also 'values' and then initialize it with _animals but getting the same error. I need to get _selectedAnimals3 populated with selected items when confirming it.
</details>
# 答案1
**得分**: 0
这是关于这个库的一个已知问题很久了,为了避免这个问题,你应该将`MultiSelectBottomSheetField<Animal?>`的类型参数设为可为空。
你的代码应该如下所示:
```dart
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
  static final 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"),
  ];
  final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
  List<Animal?> _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // 在这里进行更新
  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField<Animal?>(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text("Animals"),
        buttonText: const Text("Favorite Animals"),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return "Required";
          }
          List<String> names = values.map((e) => e!.name).toList(); // 在这里进行更新
          if (names contains ("Frog")) {
            return "Frogs are weird!";
          }
          return null;
        },
        onConfirm: (List<Animal?> values) {
          // 在这里进行更新
          setState(() {
            _selectedAnimals3 = values;
          });
          _multiSelectKey.currentState?.validate();
        },
        chipDisplay: MultiSelectChipDisplay(
          onTap: (item) {
            setState(() {
              _selectedAnimals3.remove(item);
            });
            _multiSelectKey.currentState?.validate();
          },
        ),
      ),
    );
  }
}
我建议你找到其他库来满足你的需求。
已编辑
我已经分支了这个库来解决这个问题。
我看到有多个待审核的PR,开发者似乎不活跃。
在pubspecs.yaml中添加以下行:
  multi_select_flutter:
    git: https://github.com/alexsunderlion/multi_select_flutter.git
然后你的代码应该如下所示:
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
  static final 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"),
  ];
  final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
  List<Animal> _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // 在这里进行更新
  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField<Animal>(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text("Animals"),
        buttonText: const Text("Favorite Animals"),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return "Required";
          }
          List<String> names = values.map((e) => e.name).toList(); // 在这里进行更新
          if (names.contains("Frog")) {
            return "Frogs are weird!";
          }
          return null;
        },
        onConfirm: (List<Animal> values) {
          // 在这里进行更新
          setState(() {
            _selectedAnimals3 = values;
          });
          _multiSelectKey.currentState?.validate();
        },
        chipDisplay: MultiSelectChipDisplay(
          onTap: (item) {
            setState(() {
              _selectedAnimals3.remove(item);
            });
            _multiSelectKey.currentState?.validate();
          },
        ),
      ),
    );
  }
}
英文:
This is a known issue on this library for long back, to avoid this issue, you should make MultiSelectBottomSheetField<Animal?> type parameter as nullable.
Your code should be like as following
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
  static final 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"),
  ];
  final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
  List<Animal?> _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // Update here
  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField<Animal?>(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text("Animals"),
        buttonText: const Text("Favorite Animals"),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return "Required";
          }
          List<String> names = values.map((e) => e!.name).toList(); // Update here
          if (names.contains("Frog")) {
            return "Frogs are weird!";
          }
          return null;
        },
        onConfirm: (List<Animal?> values) {
          // Update here
          setState(() {
            _selectedAnimals3 = values;
          });
          _multiSelectKey.currentState?.validate();
        },
        chipDisplay: MultiSelectChipDisplay(
          onTap: (item) {
            setState(() {
              _selectedAnimals3.remove(item);
            });
            _multiSelectKey.currentState?.validate();
          },
        ),
      ),
    );
  }
}
I suggest you to find some other library to achieve your requirement.
Edited
I have forked the library to solve this issue.
I have seen there are multiple PRs under review, looks developer is inactive.
Add change the pubspecs.yaml with following line
  multi_select_flutter:
    git: https://github.com/alexsunderlion/multi_select_flutter.git
And you code should be as following.
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static final 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"),
];
final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
List<Animal> _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e.name).toList(); // Update here
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal> values) {
// Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论