繁体   English   中英

在DropdownButton中选择项目会导致Flutter引发错误

[英]Selection of Item in DropdownButton causes Flutter to throw error

我目前正在尝试从REST API检索数据(标签),并使用该数据填充一个可以成功完成的下拉菜单,但是在选择该项目时,出现以下错误,根据错误, 意味着“已选择”值不是值列表的成员”:

项目== null || 值== null || items.where(((DropdownMenuItem item)=> item.value == value).length == 1':不正确。

这是在下拉菜单显示我的选定项目之后发生的。 但是,这不是应该发生的错误,因为我已经完成了必要的日志记录,以检查数据是否确实分配给了相关列表。 谁能帮我解决这个问题? 我已经将其隔离到起源于DropdownButton的onChangedsetState()方法,但是似乎无法理解为什么这会引起问题。 任何帮助将不胜感激!

我的代码如下:

class _TodosByTagsHomePageState extends State<TodosByTagsHomePage> {
    Tag selectedTag;

    final Logger log = new Logger('TodosByTags');

    @override
    Widget build(BuildContext context) {
      return Scaffold(
          appBar: AppBar(
            title: Text("Second Screen"),
          ),
          body: ListView(
              children: <Widget>[
                FutureBuilder<List<Tag>> (
                    future: fetchTags(),
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        log.info("Tags are present");
                        _tagsList = snapshot.data;
                        return DropdownButton<Tag>(
                          value: selectedTag,
                          items: _tagsList.map((value) {
                            return new DropdownMenuItem<Tag>(
                              value: value,
                              child: Text(value.tagName),
                            );
                          }).toList(),
                          hint: Text("Select tag"),
                          onChanged: (Tag chosenTag) {
                            setState(() {
                              log.info("In set state");
                              selectedTag = chosenTag;
                              Scaffold.of(context).showSnackBar(new SnackBar(content: Text(selectedTag.tagName)));
                            });
                          },
                        ) ;
                      } else if (snapshot.hasError) {
                        return Text("${snapshot.error}");
                      }

                      return Container(width: 0.0, height: 0.0);
                    }),
              ])
      );
    }

// Async method to retrieve data from REST API
      Future<List<Tag>> fetchTags() async {
        final response =
        await http.get(REST_API_URL);

        if (response.statusCode == 200) {
          // If the call to the server was successful, parse the JSON
          var result = compute(parseData, response.body);
          return result;
        } else {
          // If that call was not successful, throw an error.
          throw Exception('Failed to load post');
        }
      }

      static List<Tag> parseData(String response) {
        final parsed = json.decode(response);

        return (parsed["data"] as List).map<Tag>((json) =>
        new Tag.fromJson(json)).toList();
      }

      List<Tag> _tagsList = new List<Tag>();

    }

// Model for Tag
    class Tag {
      final String tagName;
      final String id;
      final int v;

      Tag({this.id, this.tagName, this.v});

      factory Tag.fromJson(Map<String, dynamic> json) {
        return new Tag(
          id: json['_id'],
          tagName: json['tagName'],
          v: json['__v'],
        );
      }
    }

这样更新代码,我认为这样的问题是,在FutureBuilder中调用setState并调用fetchTags()fetchTags()移至initState()一次即可调用

class _TodosByTagsHomePageState extends State<TodosByTagsHomePage> {
      Tag selectedTag;
      Future<List<Tag>> _tags;
      @override
      void initState() {
         _tags = fetchTags();
        super.initState();
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("Second Screen"),
            ),
            body: ListView(children: <Widget>[
              FutureBuilder<List<Tag>>(
                  future: _tags,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return DropdownButton<Tag>(
                        value: selectedTag,
                        items: snapshot.data.map((value) {
                          print(value);
                          return  DropdownMenuItem<Tag>(
                            value: value,
                            child: Text(value.tagName),
                          );
                        }).toList(),
                        hint: Text("Select tag"),
                        onChanged: (Tag chosenTag) {
                          setState(() {
                            selectedTag = chosenTag;
                          });
                        },
                      );
                    } else if (snapshot.hasError) {
                      return Text("${snapshot.error}");
                    }

                    return Container(width: 0.0, height: 0.0);
                  }),
            ]));
      }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM