【问题标题】:How to fetch a list of map JSON to a DropdownMenuItem?如何将地图 JSON 列表获取到 DropdownMenuItem?
【发布时间】:2020-04-05 13:42:48
【问题描述】:

我这里有一个 JSON 对象:

{
    "error": "0",
    "message": "Succesfully fetched",
    "data": [
        {
            "status": true,
            "_id": "5df0b94841f0331baf1357bb",
            "name": "test group",
            "description": "test description",
            "created_date": "2019-12-11T09:39:20.151Z",
            "__v": 0
        },
        {
            "status": true,
            "_id": "5df0df507091683d2f1ad0cf",
            "name": "new group",
            "created_date": "2019-12-11T12:21:36.283Z",
            "__v": 0
        }
    ]
}

我想将数据下的名称参数提取到DropDownMenuList。我这里有一个数据模型:

class dataArray {
//  final dynamic status;
  final dynamic id;
  final dynamic groupName;

//  final dynamic description;
//  final dynamic created_date;
//  final dynamic v;


  dataArray(this.groupName, this.id);


  dataArray.fromJson(Map jsonMap)
      : groupName = jsonMap['name'],
        id = jsonMap['_id'];


  Map toMapData(){
    var mapGroup = new Map<String, dynamic>();
    mapGroup["name"] = groupName;
    mapGroup['_id'] = id;
    return mapGroup;

  }

}

获取函数:

Future<List<dataArray>> gettaskData() async {
  List<dataArray> list;
  String link = ""; //Cannot provide this due to confidentiality
  var res = await http
      .get(Uri.encodeFull(link), headers: {"Accept": "application/json"});
  print(res.body);
  if (res.statusCode == 200) {
    var data = json.decode(res.body);
    var rest = data["data"] as List;
    var error = data['error'];
    print("this is error = $error");
    print(rest);
    list = rest.map<dataArray>((json) => dataArray.fromJson(json)).toList();
  }
  print("List Size: ${list.length}");
  return list;
}

此方法成功地将项目提取到 ListView.builder 小部件中,但我对如何将其提取到 List&lt;DropdownMenuItem&lt;T&gt;&gt; items 有点迷茫。

我已经尝试过这些解决方案:

第一个链接似乎是获取列表而不是地图,第二个链接显示的是地图,而在我的 JSON 列表中,我必须显示地图列表中的值。

编辑:根据接受的答案,我还修改了 initJson 方法到这个 -

  Future initJson() async {
    _list = await loadJsonFromAsset();
//print("Printing _List = ${_list[0].groupName}");
//    if (_list.length > 0) {
    setState(() {
      for(int i =0; i<=_list.length - 1; i++) {
        _selectedMenuItem = _list[i];
      }
    });

//      }
  }

这显示了 api 中存在的每个对象的名称参数。

【问题讨论】:

标签: flutter fetch


【解决方案1】:

这是一个可行的解决方案,因为您不喜欢提供您的 api url,所以我将提供的 json 添加到文件中并加载它以详细说明:

要记住的几件事:

  • 请注意,您的命名约定不是很好。我不喜欢那样 正因为如此,我将dataArray 重命名为DataModel(这不是很好 名称,但由于演示,好的)。
  • 如果你想在获取数据的同时显示一些东西,你可以换行 DropDownButtonFutureBuilder 与默认值。
  • 你可以避免 dynamicfinal 因为 Dart 可以推断数据 类型。无论如何,我总是尽可能地使用静态类型来避免 复杂性并使我的生活变得轻松(因为这给了编译时间 错误消息)。

在我的示例中,我没有使用FutureBuilder。您可以参考其他答案。

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:so_answers/drop_down/model.dart';

class DropDownDemo extends StatefulWidget {
  @override
  _DropDownDemoState createState() => _DropDownDemoState();
}

class _DropDownDemoState extends State<DropDownDemo> {
  List<DataModel> _list = [];
  DataModel _selectedMenuItem;

  String selected = "hello";

  Future<List<DataModel>> loadJsonFromAsset() async {
    String data =
        await DefaultAssetBundle.of(context).loadString("assets/data.json");
    final decoded = json.decode(data);
    try {
      return (decoded != null)
          ? decoded["data"]
              .map<DataModel>((item) => DataModel.fromJson(item))
              .toList()
          : [];
    } catch (e) {
      debugPrint(e.toString());
      return [];
    }
  }

  Future initJson() async {
    _list = await loadJsonFromAsset();

    if (_list.length > 0) {
      _selectedMenuItem = _list[0];
    }
  }

  DropdownMenuItem<DataModel> buildDropdownMenuItem(DataModel item) {
    return DropdownMenuItem(
      value: item, // you must provide a value
      child: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Text(item.groupName ?? ""),
      ),
    );
  }

  Widget buildDropdownButton() {
    return Center(
      child: Padding(
        padding: EdgeInsets.all(20),
        child: DropdownButton<DataModel>(
          elevation: 1,
          hint: Text("Select one"),
          isExpanded: true,
          underline: Container(
            height: 2,
            color: Colors.black12,
          ),
          items: _list.map((item) => buildDropdownMenuItem(item)).toList(),
          value: _selectedMenuItem, // values should match
          onChanged: (DataModel item) {
            setState(() => _selectedMenuItem = item);
          },
        ),
      ),
    );
  }

  @override
  void initState() {
    initJson();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: buildDropdownButton(),
    );
  }
}

来自文档的关于DropDownButton

/// A material design button for selecting from a list of items.
///
/// A dropdown button lets the user select from a number of items. The button
/// shows the currently selected item as well as an arrow that opens a menu for
/// selecting another item.
///
/// The type `T` is the type of the [value] that each dropdown item represents.
/// All the entries in a given menu must represent values with consistent types.
/// Typically, an enum is used. Each [DropdownMenuItem] in [items] must be
/// specialized with that same type argument.
///
/// The [onChanged] callback should update a state variable that defines the
/// dropdown's value. It should also call [State.setState] to rebuild the
/// dropdown with the new value.

更多信息请参考文档:https://api.flutter.dev/flutter/material/DropdownButton-class.html

【讨论】:

  • 感谢@Blasanka 的回答!我将方法loadJsonFromAsset 替换为gettaskData(此方法包含带有api url 的提取),现在它可以正确显示值了。
【解决方案2】:

你可以像这样制作下拉菜单,

FutureBuilder<List<dataArray>>(
        future: gettaskData(),
        builder: (BuildContext, snapshot){
          if (snapshot.data != null) {
            //print('project snapshot data is: ${projectSnap.data}');
            return Container(
              decoration: BoxDecoration(
                  borderRadius: new BorderRadius.circular(3),
                  color: Colors.grey[300]),
              child: DropdownButtonHideUnderline(
                child: DropdownButton(
                  items: snapshot.data.map((value) {
                    return new DropdownMenuItem(
                      value: value.id,
                      child: new Text(
                        value.groupName,
                      ),
                    );
                  }).toList(),
                  value: select_dataItem == "" ? null : select_dataItem,
                  onChanged: (v) {
                    FocusScope.of(context).requestFocus(new FocusNode());
                    setState(() {
                      select_dataItem = v;
                      print("selected ${select_dataItem}");
                    });
                  },
                  isExpanded: true,
                  hint: Text(
                    'Select Source',
                  ),
                ),
              ),
            );
          }
          if(snapshot.data == null){
            return Text("No Data");
          }
          return Container();
        },
      ),

【讨论】:

    猜你喜欢
    • 2021-10-31
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    相关资源
    最近更新 更多