【问题标题】:How to fetch a list of maps to a calendar? [Flutter]如何将地图列表获取到日历? [扑]
【发布时间】:2019-12-30 07:48:00
【问题描述】:

我这里有一个 json 对象 -

{
    "error": "0",
    "message": "Got it!",
    "data": [
        {
            "status": false,
            "_id": "5e04a27692928701258b9b06",
            "group_id": "5df8aaae2f85481f6e31db59",
            "date": "2019-12-29T00:00:00.000Z",
            "title": "new task",
            "priority": 5,
            "description": "just a description",
            "tasks": [],
            "created_date": "2019-12-26T12:07:18.301Z",
            "__v": 0
        }
    ]
}

我正在使用这个插件在我的应用程序中实现一个日历 - https://github.com/aleksanderwozniak/table_calendar

我想以Map <DateTime, List> 的格式获取json 对象(插件有一个使用Map <DateTime, List> 显示事件的断言),其中“日期”参数应映射到“标题”参数。

插件使用 initState 创建一些硬编码事件 -


 Map<DateTime, List> _events;
  @override
  void initState() {
    super.initState();

    final _selectedDay = DateTime.now();


    _events = {_selectedDay : ["event 1"]};
  }

我能否就如何获取 json 对象并将其转换为 Map&lt;DateTime, List&gt;? Fetching the data on initState to _events 的格式获得一些帮助 ` 应该没问题。

数据模型 -

class Post {
  dynamic markComplete;
  dynamic groupID;
  dynamic date;
  dynamic taskName;
  dynamic taskID;
//dynamic subtasks;

  dynamic priority;
  dynamic description;

/// IMPLEMENT PARAMETERS AFTER CONFIRMING WITH VAMSHI

  Post({
    this.markComplete,
    this.groupID,
    this.taskID,
    this.date,
    this.taskName,
//    this.subtasks,

    this.priority,
    this.description,
  });

/// MIGHT NEED TO CHANGE JSON VALUES; CONFIRM FROM VAMSHI
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
        markComplete : json['status'],
        groupID : json['group_id'],
      taskID: json["_id"],
      date : json['date'],
      taskName : json['title'],
//      subtasks : json['subTasks'],

      priority : json['priority'],
      description : json['description']
    );
  }



  Map toMapFetch() {
    var map = new Map<dynamic, dynamic>();
//    map['status'] = markComplete;
//    map["group_id"] = taskid;
//    map['date'] = date;
    map['title'] = taskName;
//    map['subTasks'] = subtasks;
//
//    map['priority'] = priority;
//    map['description'] = description;


    return map;
  }
}

获取方法 -

Future<Map<DateTime, List>> getTask() async {
  Map<DateTime, List> mapFetch;
  String link = baseURL + fetchTodoByDate;
  var res = await http.post(Uri.encodeFull(link), headers: {"Accept": "application/json"});
  if (res.statusCode == 200) {
 // need help in creating fetch logic here
  }
return mapFetch;
}

数据模型 =

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;

  }

}

更新了 getTask 方法 =

  Future<List<dataArray>> getTask() async {


    List<dataArray> groupMap;
    String link = baseURL + fetchGroups;
    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;

      final demoJsonMapEntries = rest.map((data) {
        return MapEntry(DateTime.parse(data['created_date']), data['name']);
      });

      demoJsonMapEntries.forEach((e) {
        // Normalize the `date` - this is necessary to ensure proper `Map` behavior
        final key = DateTime.utc(e.key.year, e.key.month, e.key.day, 12);

        _events.update(key, (list) => list..add(e.value), ifAbsent: () => [e.value]);
      });
      print(demoJsonMapEntries);
    }
    print("PRINTING MAP = $groupMap");
 return groupMap;
  }

【问题讨论】:

    标签: flutter


    【解决方案1】:

    您可以在下面复制粘贴运行完整代码
    以 3 秒延迟模拟 API 调用
    假设您在 12/29 和 12/30 有两个事件,然后使用 Event event = eventFromJson(responseString); 解析并在 for 循环后返回 mapFetch
    您可以在完整代码中获得完整的 Event 类定义

    代码sn-p

    WidgetsBinding.instance.addPostFrameCallback((_) {
          getTask().then((val) => setState(() {
                _events = val;
              }));
    
        });
    
    ...
    Future<Map<DateTime, List>> getTask() async {
        Map<DateTime, List> mapFetch = {};
    
        await Future.delayed(const Duration(seconds: 3), () {});
    
        /*String link = baseURL + fetchTodoByDate;
        var res = await http.post(Uri.encodeFull(link), headers: {"Accept": "application/json"});
        if (res.statusCode == 200) {
          // need help in creating fetch logic here
        }*/
    
        String responseString = '''
        {
        "error": "0",
        "message": "Got it!",
        "data": [
            {
                "status": false,
                "_id": "5e04a27692928701258b9b06",
                "group_id": "5df8aaae2f85481f6e31db59",
                "date": "2019-12-29T00:00:00.000Z",
                "title": "new task",
                "priority": 5,
                "description": "just a description",
                "tasks": [],
                "created_date": "2019-12-26T12:07:18.301Z",
                "__v": 0
            },
            {
                "status": false,
                "_id": "5e04a27692928701258b9b06",
                "group_id": "5df8aaae2f85481f6e31db59",
                "date": "2019-12-30T00:00:00.000Z",
                "title": "abc",
                "priority": 5,
                "description": "just a description",
                "tasks": [],
                "created_date": "2019-12-26T12:07:18.301Z",
                "__v": 0
            }
        ]
    }
        ''';
    
        Event event = eventFromJson(responseString);
    
        for (int i = 0; i < event.data.length; i++) {
          mapFetch[event.data[i].date] = [event.data[i].title];
        }
    
        return mapFetch;
      }
    

    工作演示

    完整代码

    import 'package:flutter/material.dart';
    import 'package:table_calendar/table_calendar.dart';
    // To parse this JSON data, do
    //
    //     final event = eventFromJson(jsonString);
    
    import 'dart:convert';
    
    Event eventFromJson(String str) => Event.fromJson(json.decode(str));
    
    String eventToJson(Event data) => json.encode(data.toJson());
    
    class Event {
      String error;
      String message;
      List<Datum> data;
    
      Event({
        this.error,
        this.message,
        this.data,
      });
    
      factory Event.fromJson(Map<String, dynamic> json) => Event(
            error: json["error"],
            message: json["message"],
            data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
          );
    
      Map<String, dynamic> toJson() => {
            "error": error,
            "message": message,
            "data": List<dynamic>.from(data.map((x) => x.toJson())),
          };
    }
    
    class Datum {
      bool status;
      String id;
      String groupId;
      DateTime date;
      String title;
      int priority;
      String description;
      List<dynamic> tasks;
      DateTime createdDate;
      int v;
    
      Datum({
        this.status,
        this.id,
        this.groupId,
        this.date,
        this.title,
        this.priority,
        this.description,
        this.tasks,
        this.createdDate,
        this.v,
      });
    
      factory Datum.fromJson(Map<String, dynamic> json) => Datum(
            status: json["status"],
            id: json["_id"],
            groupId: json["group_id"],
            date: DateTime.parse(json["date"]),
            title: json["title"],
            priority: json["priority"],
            description: json["description"],
            tasks: List<dynamic>.from(json["tasks"].map((x) => x)),
            createdDate: DateTime.parse(json["created_date"]),
            v: json["__v"],
          );
    
      Map<String, dynamic> toJson() => {
            "status": status,
            "_id": id,
            "group_id": groupId,
            "date": date.toIso8601String(),
            "title": title,
            "priority": priority,
            "description": description,
            "tasks": List<dynamic>.from(tasks.map((x) => x)),
            "created_date": createdDate.toIso8601String(),
            "__v": v,
          };
    }
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      List _selectedEvents;
      int _counter = 0;
      Map<DateTime, List> _events;
      CalendarController _calendarController;
      AnimationController _animationController;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      Future<Map<DateTime, List>> getTask() async {
        Map<DateTime, List> mapFetch = {};
    
        await Future.delayed(const Duration(seconds: 3), () {});
    
        /*String link = baseURL + fetchTodoByDate;
        var res = await http.post(Uri.encodeFull(link), headers: {"Accept": "application/json"});
        if (res.statusCode == 200) {
          // need help in creating fetch logic here
        }*/
    
        String responseString = '''
        {
        "error": "0",
        "message": "Got it!",
        "data": [
            {
                "status": false,
                "_id": "5e04a27692928701258b9b06",
                "group_id": "5df8aaae2f85481f6e31db59",
                "date": "2019-12-29T00:00:00.000Z",
                "title": "new task",
                "priority": 5,
                "description": "just a description",
                "tasks": [],
                "created_date": "2019-12-26T12:07:18.301Z",
                "__v": 0
            },
            {
                "status": false,
                "_id": "5e04a27692928701258b9b06",
                "group_id": "5df8aaae2f85481f6e31db59",
                "date": "2019-12-30T00:00:00.000Z",
                "title": "abc",
                "priority": 5,
                "description": "just a description",
                "tasks": [],
                "created_date": "2019-12-26T12:07:18.301Z",
                "__v": 0
            }
        ]
    }
        ''';
    
        Event event = eventFromJson(responseString);
    
        for (int i = 0; i < event.data.length; i++) {
          mapFetch[event.data[i].date] = [event.data[i].title];
        }
    
        return mapFetch;
      }
    
      void _onDaySelected(DateTime day, List events) {
        print('CALLBACK: _onDaySelected');
        setState(() {
          _selectedEvents = events;
        });
      }
    
      @override
      void initState() {
        final _selectedDay = DateTime.now();
        _selectedEvents = [];
        _calendarController = CalendarController();
        _animationController = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 400),
        );
    
        _animationController.forward();
        WidgetsBinding.instance.addPostFrameCallback((_) {
          getTask().then((val) => setState(() {
                _events = val;
              }));
          //print( ' ${_events.toString()} ');
        });
        super.initState();
      }
    
      @override
      void dispose() {
        _calendarController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                _buildTableCalendarWithBuilders(),
                const SizedBox(height: 8.0),
                const SizedBox(height: 8.0),
                Expanded(child: _buildEventList()),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    
      Widget _buildTableCalendarWithBuilders() {
        return TableCalendar(
          //locale: 'pl_PL',
          calendarController: _calendarController,
          events: _events,
          //holidays: _holidays,
          initialCalendarFormat: CalendarFormat.month,
          formatAnimation: FormatAnimation.slide,
          startingDayOfWeek: StartingDayOfWeek.sunday,
          availableGestures: AvailableGestures.all,
          availableCalendarFormats: const {
            CalendarFormat.month: '',
            CalendarFormat.week: '',
          },
          calendarStyle: CalendarStyle(
            outsideDaysVisible: false,
            weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
            holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
          ),
          daysOfWeekStyle: DaysOfWeekStyle(
            weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
          ),
          headerStyle: HeaderStyle(
            centerHeaderTitle: true,
            formatButtonVisible: false,
          ),
          builders: CalendarBuilders(
            selectedDayBuilder: (context, date, _) {
              return FadeTransition(
                opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController),
                child: Container(
                  margin: const EdgeInsets.all(4.0),
                  padding: const EdgeInsets.only(top: 5.0, left: 6.0),
                  color: Colors.deepOrange[300],
                  width: 100,
                  height: 100,
                  child: Text(
                    '${date.day}',
                    style: TextStyle().copyWith(fontSize: 16.0),
                  ),
                ),
              );
            },
            todayDayBuilder: (context, date, _) {
              return Container(
                margin: const EdgeInsets.all(4.0),
                padding: const EdgeInsets.only(top: 5.0, left: 6.0),
                color: Colors.amber[400],
                width: 100,
                height: 100,
                child: Text(
                  '${date.day}',
                  style: TextStyle().copyWith(fontSize: 16.0),
                ),
              );
            },
            markersBuilder: (context, date, events, holidays) {
              final children = <Widget>[];
    
              if (events.isNotEmpty) {
                children.add(
                  Positioned(
                    right: 1,
                    bottom: 1,
                    child: _buildEventsMarker(date, events),
                  ),
                );
              }
    
              if (holidays.isNotEmpty) {
                children.add(
                  Positioned(
                    right: -2,
                    top: -2,
                    child: _buildHolidaysMarker(),
                  ),
                );
              }
    
              return children;
            },
          ),
          onDaySelected: (date, events) {
            _onDaySelected(date, events);
            _animationController.forward(from: 0.0);
          },
          onVisibleDaysChanged: _onVisibleDaysChanged,
        );
      }
    
      void _onVisibleDaysChanged(
          DateTime first, DateTime last, CalendarFormat format) {
        print('CALLBACK: _onVisibleDaysChanged');
      }
    
      Widget _buildEventsMarker(DateTime date, List events) {
        return AnimatedContainer(
          duration: const Duration(milliseconds: 300),
          decoration: BoxDecoration(
            shape: BoxShape.rectangle,
            color: _calendarController.isSelected(date)
                ? Colors.brown[500]
                : _calendarController.isToday(date)
                    ? Colors.brown[300]
                    : Colors.blue[400],
          ),
          width: 16.0,
          height: 16.0,
          child: Center(
            child: Text(
              '${events.length}',
              style: TextStyle().copyWith(
                color: Colors.white,
                fontSize: 12.0,
              ),
            ),
          ),
        );
      }
    
      Widget _buildHolidaysMarker() {
        return Icon(
          Icons.add_box,
          size: 20.0,
          color: Colors.blueGrey[800],
        );
      }
    
      Widget _buildEventList() {
        return ListView(
          children: _selectedEvents
              .map((event) => Container(
                    decoration: BoxDecoration(
                      border: Border.all(width: 0.8),
                      borderRadius: BorderRadius.circular(12.0),
                    ),
                    margin:
                        const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
                    child: ListTile(
                      title: Text(event.toString()),
                      onTap: () => print('$event tapped!'),
                    ),
                  ))
              .toList(),
        );
      }
    }
    

    【讨论】:

    • 优秀的答案!只是一个简单的疑问 - 你能否简单地展示一个关于如何在使用 URL 时传递 responseString 的示例?即如何从 API 而不是硬编码的 json 对象发送响应正文?我试着玩了一下,但我不知道如何让它工作。我希望我可以提供 API,但由于我的公司政策,我不能这样做。
    • 你的 getTask() 看起来不错。只需使用 if (res.statusCode == 200) { Event event = eventFromJson(res.body); }
    • 因为我没有你的api。我所能做的就是模拟响应。让我知道它是否适用于 eventFromJson(res.body);
    • 我已经以这种方式修改了 getTask() 函数 - ``` ... String link = baseURL + fetchGroups; var res = await http.get(Uri.encodeFull(link), headers: {"Accept": "application/json"}); print("打印 res 正文 = ${res.body}"); if (res.statusCode == 200) { 事件事件 = eventFromJson(res.body); for (int i = 0; i
    • 您的代码看起来不错。你能识别错误行/代码吗?
    【解决方案2】:

    我觉得你的 fetch 方法应该是这样的:

      Future<List<Post>> getData() async{
      String link = baseURL + fetchTodoByDate;
      var res = await http.post(Uri.encodeFull(link), headers: {"Accept": "application/json"});
    
    var fetch =  List<Data>();
    if (res.statusCode == 200 ) {
      var datesJson = json.decode(res.body);
      for(var dateJson in datesJson){
        fetch.add(Data.fromJson((dateJson)));
      }
    }
    return fetch;
    

    }

    【讨论】:

      猜你喜欢
      • 2020-04-05
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多