簡體   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