Flutter DropdownButton - 从 REST Web 服务填充项目

Posted

技术标签:

【中文标题】Flutter DropdownButton - 从 REST Web 服务填充项目【英文标题】:Flutter DropdownButton - populate items from rest webservice 【发布时间】:2019-07-26 22:24:57 【问题描述】:

我的 fetchCities() 方法返回 Future<List<City>> 并从 rest webservice 加载数据。填充项目的代码:

 Widget buildCitiesSelector()

    return new Center(
        child: FutureBuilder(
            future: fetchCities() ,
            builder: (context, snapshot)
              if (snapshot.hasData) 
                return new DropdownButton <City>(
                    hint: Text('Wybierz miasto'),
                  items: snapshot.data.map<DropdownMenuItem<City>>((City value) 
                    return DropdownMenuItem<City>(
                      value: value,
                      child: Text(value.name),
                    );
                  ).toList(),
                  onChanged: (value) 
                      setState(() _selectedCity = value;);
                  ,
                  value: _selectedCity,
                );
              
              else
                return CircularProgressIndicator();
              
            

        )

    );
  

结果:项目在选择器中正确显示。但是,在选择任何特定项目时,我会得到异常:

I/flutter (13910):══╡ 小部件库发现异常 ╞═════════════════════════════════════════════════ ══════════ I/颤振 (13910):以下断言被抛出构建 FutureBuilder>(脏,状态:I/flutter(13910): _FutureBuilderState>#dacd9): I/flutter (13910): 'package:flutter/src/material/dropdown.dart': 断言失败:行 560 位置 15: '项目 == 空 ||我/颤振(13910):items.isEmpty || 值 == 空 || items.where((DropdownMenuItem item) => item.value == I/flutter (13910): value).length == 1': 不正确。

如何正确选择项目?有什么想法吗?

【问题讨论】:

我觉得你的问题和我的很相似:***.com/questions/61720324/… 【参考方案1】:

在这种情况下,您不应使用FutureBuilder。而是获取initState() 中的数据,然后使用setState() 进行重建以更新视图。

如果 fetchCities() 每次调用时都会创建一个新的 Future,那么 build() 将在每次重新构建 UI 时调用该 fetch(可能非常频繁)

https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html

未来一定是更早获得的,例如在 State.initState 期间,...

【讨论】:

为什么不使用FutureBuilder?我设法在initState 中获得了未来的城市列表(通过调用我的fetchCities 方法,然后将检索到的列表传递给FutureBuilder,但它不起作用。 @user1209216 遵循此答案并检查来自DropdownMenuItemvalue: 必须是某种id,要比较的东西你不能像你在问题中那样比较对象。跨度> 我实际上认为这种方法没有问题。在 initState 中检索到的未来,传递给 FutureBuilder。我刚刚将 fetchCities 移至 initState【参考方案2】:
      child: FutureBuilder(
            future: Webservice().load(Country.countries) ,
            builder: (context, snapshot)
              if(snapshot.hasError)
                return Text(snapshot.error);

              if (snapshot.hasData) 
                return  DropdownButtonFormField(
                  decoration: new InputDecoration(icon: Icon(Icons.language)), //, color: Colors.white10
                  value: selectedCountry,
                  items: snapshot.data.map<DropdownMenuItem<Country>>((Country country) 

                       return  DropdownMenuItem<Country>(

                                value: country,
                                child: Text(country.name, style: TextStyle(color: Color.fromRGBO(58, 66, 46, .9))),

                              );
                  )
                          .toList(),


                  onChanged: (Country newValue) 
                      setState(() => selectedCountry = newValue);
                      // selectedCountry = newValue;
                      print(newValue.id);
                      print(newValue.name);
                  ,
               );

              
              return CircularProgressIndicator();

【讨论】:

【参考方案3】:

我今天遇到了同样的问题,经过一番挖掘,我发现我的代码中有一个错误:DropdownButton 中的值不在项目列表中。

我(错误地)假设下拉菜单会处理“空”值 - 但事实并非如此。

【讨论】:

【参考方案4】:

您可以在 initState 中声明 Future 和 init,并在 FutureBuilder 中使用这个未来。

City cityModel;
Future _future;

@override
  void initState() 
    _future = fetchCities();
    super.initState();
  

body: FutureBuilder<List<City>>(
          future: _future,  

【讨论】:

以上是关于Flutter DropdownButton - 从 REST Web 服务填充项目的主要内容,如果未能解决你的问题,请参考以下文章

Dart / flutter:DropdownButton在值更改时导致异常

flutter DropdownButton使用

Flutter - 如何在小部件测试中选择 DropdownButton 项

Flutter GetBuilder Dependent DropDownButton - 即使值已被重置,也应该只有一项具有 [DropdownButton] 的值

如何像 Flutter 中的 Spinner 一样在 DropdownButton 下方打开 DropDown 对话框?

Flutter:如何将 DropdownButton 菜单图标对齐到最右边?