选择值时出现颤振下拉按钮错误[使用来自 api 和 FutureBuilder 的数据]

Posted

技术标签:

【中文标题】选择值时出现颤振下拉按钮错误[使用来自 api 和 FutureBuilder 的数据]【英文标题】:Flutter dropdownbutton error when selecting a value [using Data from api and FutureBuilder] 【发布时间】:2020-01-18 11:38:26 【问题描述】:

大家好,我正面临一个问题,我正在使用此代码从 api 检索数据

class carLists

carLists();
getCarsFromNetwork(String jsonUrl) async 
List<Cars> list;
String link = jsonUrl;
var res = await http.get(Uri.encodeFull(link),headers: "Accept":"Application/json");
if (res.statusCode == 200) 
var data = json.decode(res.body);
var list = data["cars"] as List;
List<Cars> imagesList = list.map((i) => Cars.fromJson(i)).toList();

return imagesList;


List<DropdownMenuItem> getCars(List<Cars> carPlates)
List<DropdownMenuItem<String>> ordersType = new List<DropdownMenuItem<String>>();

for(var i = 0 ; i<carPlates.length;i++ ) 


    ordersType.add(DropdownMenuItem(
      value: carPlates[i].carPlate, child: Text(carPlates[i].carPlate),));


return ordersType;



并使用这两个函数实现一个下拉按钮来获取数据并返回下拉菜单列表:`

Future<List<Cars>> foo(String link) async

carPlates =  await carLists().getCarsFromNetwork(link);
print(carPlates.length);
return carPlates;


getItems(List values) 
List<DropdownMenuItem<String>> ordersType = new List<
    DropdownMenuItem<String>>();
for (var i = 0; i > values.length; i++) 
  ordersType.add(DropdownMenuItem(value: values[i], child: values[i],));

  return ordersType;


`并使用此代码填充 DropdownButton

Container(

    child: FutureBuilder(
        future: foo(url) ,
        builder: (context, snapshot)
     if(snapshot.hasData)
       
         return new DropdownButton(
           iconDisabledColor: Colors.black,
           isExpanded: true,
           icon: Icon(FontAwesomeIcons.arrowCircleDown),
           iconSize: 14,
           style: TextStyle(fontSize: 16, color: Colors.black),
           iconEnabledColor: Colors.deepOrange,
           items: carLists().getCars(carPlates),
           value: dropTyreBrand,
           onChanged: (val) 
             setState(() 
               dropTyreBrand = val;

             );
           ,
         );
       else

          return CircularProgressIndicator();

     
        
    ),
  ) ,

值已填充,一切都很好,但是当我从下拉列表中选择一个值时,它会因此错误而崩溃

I/flutter (4578): 在构建 FutureBuilder>(dirty, state: 我/颤振(4578):_FutureBuilderState>#f394d): I/flutter(4578):'package:flutter/src/material/dropdown.dart':断言失败:第 608 行 pos 15:'items == null || 我/颤振(4578):items.isEmpty ||值 == 空 || items.where((DropdownMenuItem item) => item.value == I/flutter (4578): value).length == 1': 不正确。 我/颤振(4578): I/flutter (4578):要么断言表明框架本身有错误,要么我们应该提供实质性的 I/flutter (4578):此错误消息中的更多信息可帮助您确定和修复根本原因。 I/flutter (4578):在任何一种情况下,请通过在 GitHub 上提交错误来报告此断言: 我/颤振(4578):https://github.com/flutter/flutter/issues/new?template=BUG.md 我/颤振(4578): I/flutter (4578):当异常被抛出时,这是堆栈: I/flutter (4578): #2 新的下拉按钮

【问题讨论】:

【参考方案1】:

如果你使用 FutureBuilder 并且在项目中你需要使用 snapshot.data 这就是为什么错误说 items == null 或 items 为空

演示代码sn-p

return DropdownButton<Designations>(
                    items: snapshot.data
                        .map((designation) => DropdownMenuItem<Designations>(
                              child: Text(designation.designation),
                              value: designation,
                            ))
                        .toList(),

演示完整代码

import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

// To parse this JSON data, do
//
//     final designations = designationsFromJson(jsonString);

List<Designations> designationsFromJson(String str) => List<Designations>.from(
    json.decode(str).map((x) => Designations.fromJson(x)));

String designationsToJson(List<Designations> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Designations 
  String designationId;
  String designation;

  Designations(
    this.designationId,
    this.designation,
  );

  factory Designations.fromJson(Map<String, dynamic> json) => Designations(
        designationId: json["DesignationId"],
        designation: json["Designation"],
      );

  Map<String, dynamic> toJson() => 
        "DesignationId": designationId,
        "Designation": designation,
      ;


class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: JsonApiDropdown(),
    );
  


class JsonApiDropdown extends StatefulWidget 
  @override
  JsonApiDropdownState createState() 
    return new JsonApiDropdownState();
  


class JsonApiDropdownState extends State<JsonApiDropdown> 
  Designations _currentDesignation;

  final String uri = 'https://jsonplaceholder.typicode.com/users';

  Future<List<Designations>> _fetchDesignation() async 
    String jsonString =
        '[  "DesignationId": "CDG0008", "Designation": "Avp - Associate Vice President" ,  "DesignationId": "CDG0004", "Designation": "Ceo - Chief Executive Officer"  ]';
    final designations = designationsFromJson(jsonString);
    return designations;
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('Fetching data from JSON - DropdownButton'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            FutureBuilder<List<Designations>>(
                future: _fetchDesignation(),
                builder: (BuildContext context,
                    AsyncSnapshot<List<Designations>> snapshot) 
                  if (!snapshot.hasData) return CircularProgressIndicator();
                  return DropdownButton<Designations>(
                    items: snapshot.data
                        .map((designation) => DropdownMenuItem<Designations>(
                              child: Text(designation.designation),
                              value: designation,
                            ))
                        .toList(),
                    onChanged: (Designations value) 
                      setState(() 
                        _currentDesignation = value;
                      );
                    ,
                    isExpanded: false,
                    //value: _currentUser,
                    hint: Text('Select User'),
                  );
                ),
            SizedBox(height: 20.0),
            _currentDesignation != null
                ? Text("designation: " +
                    _currentDesignation.designation +
                    "\n id: " +
                    _currentDesignation.designationId)
                : Text("No selected"),
          ],
        ),
      ),
    );
  

【讨论】:

以上是关于选择值时出现颤振下拉按钮错误[使用来自 api 和 FutureBuilder 的数据]的主要内容,如果未能解决你的问题,请参考以下文章

为啥在颤振项目中添加启动器图标时出现错误?

当我对颤振项目进行颤振清理时出现错误

Flutter:如何根据选择的第一个下拉按钮值设置第二个下拉按钮(多级相关按钮)的值?

使用来自 Angular JS 的 Web API 令牌身份验证时出现错误请求 (400)

使用颤振运行命令时出现此错误

使用 Firestore 获取数据时出现颤振错误