How to fix _TypeError (type 'List<Animal?>' is not a subtype of type 'List<Animal>?' of 'value')

huangapple go评论80阅读模式
英文:

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&#39;s wrong with my code. Whatever I try I am still getting this error when trying to confirm my selection in multiselect widget.
Here&#39;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 &#39;values&#39; 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&lt;Animal?&gt;`的类型参数设为可为空。

你的代码应该如下所示:
```dart
class _ParticipantsToSelectState extends State&lt;ParticipantsToSelect&gt; {
  static final List&lt;Animal&gt; _animals = [
    Animal(id: 1, name: &quot;Lion&quot;),
    Animal(id: 2, name: &quot;Flamingo&quot;),
    Animal(id: 3, name: &quot;Hippo&quot;),
    Animal(id: 4, name: &quot;Horse&quot;),
    Animal(id: 5, name: &quot;Tiger&quot;),
    Animal(id: 6, name: &quot;Penguin&quot;),
    Animal(id: 7, name: &quot;Spider&quot;),
    Animal(id: 8, name: &quot;Snake&quot;),
    Animal(id: 9, name: &quot;Bear&quot;),
    Animal(id: 10, name: &quot;Beaver&quot;),
  ];

  final _items = _animals.map((animal) =&gt; MultiSelectItem&lt;Animal&gt;(animal, animal.name)).toList();
  List&lt;Animal?&gt; _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey&lt;FormFieldState&lt;List&lt;Animal&gt;&gt;&gt;(); // 在这里进行更新

  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField&lt;Animal?&gt;(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text(&quot;Animals&quot;),
        buttonText: const Text(&quot;Favorite Animals&quot;),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return &quot;Required&quot;;
          }
          List&lt;String&gt; names = values.map((e) =&gt; e!.name).toList(); // 在这里进行更新
          if (names contains (&quot;Frog&quot;)) {
            return &quot;Frogs are weird!&quot;;
          }
          return null;
        },
        onConfirm: (List&lt;Animal?&gt; 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&lt;ParticipantsToSelect&gt; {
  static final List&lt;Animal&gt; _animals = [
    Animal(id: 1, name: &quot;Lion&quot;),
    Animal(id: 2, name: &quot;Flamingo&quot;),
    Animal(id: 3, name: &quot;Hippo&quot;),
    Animal(id: 4, name: &quot;Horse&quot;),
    Animal(id: 5, name: &quot;Tiger&quot;),
    Animal(id: 6, name: &quot;Penguin&quot;),
    Animal(id: 7, name: &quot;Spider&quot;),
    Animal(id: 8, name: &quot;Snake&quot;),
    Animal(id: 9, name: &quot;Bear&quot;),
    Animal(id: 10, name: &quot;Beaver&quot;),
  ];

  final _items = _animals.map((animal) =&gt; MultiSelectItem&lt;Animal&gt;(animal, animal.name)).toList();
  List&lt;Animal&gt; _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey&lt;FormFieldState&lt;List&lt;Animal&gt;&gt;&gt;(); // 在这里进行更新

  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField&lt;Animal&gt;(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text(&quot;Animals&quot;),
        buttonText: const Text(&quot;Favorite Animals&quot;),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return &quot;Required&quot;;
          }
          List&lt;String&gt; names = values.map((e) =&gt; e.name).toList(); // 在这里进行更新
          if (names.contains(&quot;Frog&quot;)) {
            return &quot;Frogs are weird!&quot;;
          }
          return null;
        },
        onConfirm: (List&lt;Animal&gt; 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&lt;Animal?&gt; type parameter as nullable.

Your code should be like as following

class _ParticipantsToSelectState extends State&lt;ParticipantsToSelect&gt; {
  static final List&lt;Animal&gt; _animals = [
    Animal(id: 1, name: &quot;Lion&quot;),
    Animal(id: 2, name: &quot;Flamingo&quot;),
    Animal(id: 3, name: &quot;Hippo&quot;),
    Animal(id: 4, name: &quot;Horse&quot;),
    Animal(id: 5, name: &quot;Tiger&quot;),
    Animal(id: 6, name: &quot;Penguin&quot;),
    Animal(id: 7, name: &quot;Spider&quot;),
    Animal(id: 8, name: &quot;Snake&quot;),
    Animal(id: 9, name: &quot;Bear&quot;),
    Animal(id: 10, name: &quot;Beaver&quot;),
  ];

  final _items = _animals.map((animal) =&gt; MultiSelectItem&lt;Animal&gt;(animal, animal.name)).toList();
  List&lt;Animal?&gt; _selectedAnimals3 = [];
  final _multiSelectKey = GlobalKey&lt;FormFieldState&lt;List&lt;Animal&gt;&gt;&gt;(); // Update here

  @override
  void initState() {
    _selectedAnimals3 = _animals;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: MultiSelectBottomSheetField&lt;Animal?&gt;(
        key: _multiSelectKey,
        initialChildSize: 0.7,
        maxChildSize: 0.95,
        title: const Text(&quot;Animals&quot;),
        buttonText: const Text(&quot;Favorite Animals&quot;),
        items: _items,
        searchable: true,
        validator: (values) {
          if (values == null || values.isEmpty) {
            return &quot;Required&quot;;
          }
          List&lt;String&gt; names = values.map((e) =&gt; e!.name).toList(); // Update here
          if (names.contains(&quot;Frog&quot;)) {
            return &quot;Frogs are weird!&quot;;
          }
          return null;
        },
        onConfirm: (List&lt;Animal?&gt; 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&lt;ParticipantsToSelect&gt; {
static final List&lt;Animal&gt; _animals = [
Animal(id: 1, name: &quot;Lion&quot;),
Animal(id: 2, name: &quot;Flamingo&quot;),
Animal(id: 3, name: &quot;Hippo&quot;),
Animal(id: 4, name: &quot;Horse&quot;),
Animal(id: 5, name: &quot;Tiger&quot;),
Animal(id: 6, name: &quot;Penguin&quot;),
Animal(id: 7, name: &quot;Spider&quot;),
Animal(id: 8, name: &quot;Snake&quot;),
Animal(id: 9, name: &quot;Bear&quot;),
Animal(id: 10, name: &quot;Beaver&quot;),
];
final _items = _animals.map((animal) =&gt; MultiSelectItem&lt;Animal&gt;(animal, animal.name)).toList();
List&lt;Animal&gt; _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey&lt;FormFieldState&lt;List&lt;Animal&gt;&gt;&gt;(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField&lt;Animal&gt;(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text(&quot;Animals&quot;),
buttonText: const Text(&quot;Favorite Animals&quot;),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return &quot;Required&quot;;
}
List&lt;String&gt; names = values.map((e) =&gt; e.name).toList(); // Update here
if (names.contains(&quot;Frog&quot;)) {
return &quot;Frogs are weird!&quot;;
}
return null;
},
onConfirm: (List&lt;Animal&gt; values) {
// Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}

huangapple
  • 本文由 发表于 2023年2月19日 06:06:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496682.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定