Flutter 如何在状态更新时无法重新加载 FutureBuilder?

时间:2021-03-04 15:12:51

标签: json flutter datetime

我正在自己学习颤振。 尝试使用轮播日历制作 doto Calendar。

  • 我想在有活动的时候把日期弄大 -> 完成了

问题是

@第 238 行

如果我输入如下代码,则每当我按下日期按钮时,日历都会不断刷新。

return snapshot.hasData && _markedDateMap.events.length > 0 ...

如果我把代码写成下面这样,我可爱的大日期按钮就会变小!!

return snapshot.hasData ...

这个问题有什么解决办法吗? 请帮助我阻止未来的建设者继续建设! TT

enter image description here

import 'package:flutter/material.dart';

import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'
    show CalendarCarousel;
import 'package:flutter_calendar_carousel/classes/event.dart';
import 'package:flutter_calendar_carousel/classes/event_list.dart';
import 'package:intl/intl.dart' show DateFormat;

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

Future<List<ipoData>> fetchIPODatas(http.Client client) async {
  final response = await client.get('http://realchord.net/ipo/getIPOData.php');

  // Use the compute function to run parseIpoData in a separate isolate.
  return compute(parseIpoData, response.body);
}

// A function that converts a response body into a List<Photo>.
List<ipoData> parseIpoData(String responseBody) {
  final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();

  return parsed.map<ipoData>((json) => ipoData.fromJson(json)).toList();
}

// ignore: camel_case_types
class ipoData {
  final String ipoDate;
  final String company;

  ipoData({this.ipoDate, this.company});

  factory ipoData.fromJson(Map<String, dynamic> json) => ipoData(
        ipoDate: json['date'],
        company: json['company'],
      );
}

// factory Model.fromJson(Map<String, dynamic> json) => Model(
//     value1: json['key1'],
//     value2: json['key2'],
//     value3: json['key3'],
//     value4: json['key4'],
//   );

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'IPO calendar',
        theme: new ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: new MyHomePage(title: 'IPO calendar'));
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DateTime _currentDate = new DateTime.now();
  DateTime _currentDate2 = new DateTime.now();
  String _currentMonth = DateFormat.MMMM().format(new DateTime.now());

  DateTime _next = new DateTime(
      DateTime.now().year, DateTime.now().month + 1, DateTime.now().day);
  DateTime _prev = new DateTime(
      DateTime.now().year, DateTime.now().month - 1, DateTime.now().day);
  String _nextMonth;
  String _prevMonth;
  DateTime _targetDateTime = new DateTime.now();

//  List<DateTime> _markedDate = [DateTime(2018, 9, 20), DateTime(2018, 10, 11)];

  EventList<Event> _markedDateMap = new EventList<Event>();

  // ignore: unused_field
  CalendarCarousel _calendarCarouselNoHeader;

  // load data

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

  // List response = await fetchIPODatas(http.Client());

  @override
  Widget build(BuildContext context) {
    /// Example Calendar Carousel without header and custom prev & next button

    _calendarCarouselNoHeader = CalendarCarousel<Event>(
      onDayPressed: (DateTime date, List<Event> events) {
        this.setState(() => _currentDate2 = date);
        // events.forEach((event) => print(event.title));
      },

      //달력 기본 설정
      daysHaveCircularBorder: true,
      showOnlyCurrentMonthDate: false,
      showHeader: false,
      customGridViewPhysics: NeverScrollableScrollPhysics(),

      height: 500.0,
      daysTextStyle: TextStyle(
        fontWeight: FontWeight.w600,
        color: Colors.white, //weekend day font color
      ),
      weekendTextStyle: TextStyle(
        fontWeight: FontWeight.w600,
        color: Colors.white, //weekend day font color
      ),

      weekdayTextStyle: TextStyle(
        color: Colors.white,
        fontWeight: FontWeight.bold,
      ),
      // thisMonthDayBorderColor: Colors.grey, // border color of each day
      weekFormat: false,
//      firstDayOfWeek: 4,

      markedDatesMap: _markedDateMap,

      selectedDateTime: _currentDate2,
      targetDateTime: _targetDateTime,

      minSelectedDate: _currentDate.subtract(Duration(days: 360)),
      maxSelectedDate: _currentDate.add(Duration(days: 360)),

// //이벤트가 있는 날에 대한 설정

      // markedDateCustomShapeBorder:
      //     CircleBorder(side: BorderSide(color: Colors.yellow)),
      markedDateCustomTextStyle: TextStyle(
        fontSize: 30,
        color: Colors.white,
      ),
      // markedDateIconBorderColor: Colors.white,
      // markedDateMoreShowTotal: true,

//오늘에 대한 설정
      todayTextStyle: TextStyle(
        color: Colors.white,
      ),
      todayButtonColor: Colors.white24,
      todayBorderColor: null,

// 선택한 날에 대한 설정
      selectedDayTextStyle: TextStyle(
        color: Colors.black,
      ),
      selectedDayButtonColor: Colors.white,
      // selectedDayBorderColor: Colors.white,

// 지난 달에 대한 설정
      prevDaysTextStyle: TextStyle(
        fontSize: 16,
        color: Colors.white38,
      ),
// 다음 달에 대한 설정
      nextDaysTextStyle: TextStyle(
        fontSize: 16,
        color: Colors.white38,
      ),
      inactiveDaysTextStyle: TextStyle(
        color: Colors.white38,
        fontSize: 16,
      ),
      onCalendarChanged: (DateTime date) {
        this.setState(() {
          _targetDateTime = date;
          _currentMonth = DateFormat.MMMM().format(_targetDateTime);

          _next = new DateTime(_targetDateTime.year, _targetDateTime.month + 1,
              _targetDateTime.day);

          _nextMonth = DateFormat.MMMM().format(_next);

          _prev = new DateTime(_targetDateTime.year, _targetDateTime.month - 1,
              _targetDateTime.day);

          _prevMonth = DateFormat.M().format(_prev);
        });
      },
      onDayLongPressed: (DateTime date) {
        print('long pressed date $date');
      },
    );

    _markedDateMap.clear();

    _nextMonth = DateFormat.MMMM().format(_next);
    _prevMonth = DateFormat.M().format(_prev);

    // dotColorList.add(Colors.white);

    return new Scaffold(
        body: FutureBuilder<List<ipoData>>(
      future: fetchIPODatas(http.Client()),
      builder: (context, snapshot) {
        if (snapshot.hasError) print(snapshot.error);

        if (snapshot.connectionState == ConnectionState.done &&
            snapshot.hasData &&
            snapshot.data != null) {
          final List<ipoData> ipoDataList = snapshot.data;

          for (var i = 0; i < snapshot.data.length; i++) {
            DateTime dt = DateTime.parse(ipoDataList[i].ipoDate.toString());

            _markedDateMap.add(
                dt,
                new Event(
                  date: dt,
                  title: ipoDataList[i].company,
                  dot: Container(
                    margin: EdgeInsets.symmetric(horizontal: 1.0),
                    color: Colors.red.shade300,
                    height: 5.0,
                    width: 5.0,
                  ),
                ));
          }
        }
        return snapshot.hasData && _markedDateMap.events.length > 0
            ? SingleChildScrollView(
                child: Stack(children: [
                  Container(
                    padding: EdgeInsets.only(top: 50),
                    color: Colors.blue,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        //custom icon without header
                        Container(
                          //display Month
                          margin: EdgeInsets.only(
                            top: 20.0,
                            bottom: 16.0,
                            left: 0.0,
                            right: 0.0,
                          ),
                          padding: EdgeInsets.all(0),
                          child: new Row(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              FlatButton(
                                padding: EdgeInsets.all(0),
                                child: Text(_prevMonth,
                                    // softWrap: false,
                                    maxLines: 1,
                                    textAlign: TextAlign.right,
                                    style: TextStyle(
                                      color: Colors.white12,
                                      fontSize: 48,
                                      fontWeight: FontWeight.bold,
                                    )),
                                onPressed: () {
                                  setState(() {
                                    _targetDateTime = DateTime(
                                        _targetDateTime.year,
                                        _targetDateTime.month - 1);
                                    _currentMonth = DateFormat.MMMM()
                                        .format(_targetDateTime);
                                  });
                                },
                              ),
                              Text(
                                _currentMonth,
                                maxLines: 1,
                                style: TextStyle(
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                  fontSize: 48.0,
                                ),
                              ),
                              FlatButton(
                                child: Text(
                                  _nextMonth,
                                  softWrap: true,
                                  maxLines: 1,
                                  style: TextStyle(
                                    color: Colors.white12,
                                    fontSize: 48,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                                onPressed: () {
                                  setState(() {
                                    _targetDateTime = DateTime(
                                        _targetDateTime.year,
                                        _targetDateTime.month + 1);
                                    _currentMonth = DateFormat.MMMM()
                                        .format(_targetDateTime);
                                    _next = new DateTime(
                                        _targetDateTime.year,
                                        _targetDateTime.month + 1,
                                        _targetDateTime.day);
                                    _nextMonth =
                                        DateFormat.MMMM().format(_next);
                                    _prev = new DateTime(
                                        _targetDateTime.year,
                                        _targetDateTime.month - 1,
                                        _targetDateTime.day);
                                    _prevMonth = DateFormat.M().format(_prev);
                                  });
                                },
                              )
                            ],
                          ),
                        ),
                        Container(
                          margin: EdgeInsets.symmetric(horizontal: 16.0),
                          child: _calendarCarouselNoHeader,
                        )
                      ],
                    ),
                  ),
                  Container(
                    height: MediaQuery.of(context).size.height - 500,
                    width: MediaQuery.of(context).size.width,
                    margin: const EdgeInsets.only(top: 500),
                    padding: const EdgeInsets.only(
                      top: 40,
                      left: 15,
                    ),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(50),
                      color: Colors.white,
                    ),
                    child: Column(
                      children: [
                        EventItem(
                          company: "LGENSol",
                        )
                      ],
                    ),
                  )
                ]),
              )
            : Center(child: CircularProgressIndicator());
      },
    ));
  }
}

class EventItem extends StatefulWidget {
  // final Icon icon;
  final String company;
  // final Text category;
  // final Function() notifyParent;

  EventItem(
      {
      // @required this.icon,
      @required this.company}); //@required this.notifyParent
  @override
  _EventItemState createState() => _EventItemState();
}

class _EventItemState extends State<EventItem> {
  get futureAlbum => null;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Row(
          children: [
            Icon(
              Icons.favorite,
              color: Colors.pink,
              size: 24.0,
            ),
            Padding(
              padding: EdgeInsets.all(12.0),
              child: Text(widget.company,
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 20,
                  )),
            ),
            Padding(
              padding: EdgeInsets.all(5.0),
              child: Text("(청약)",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 20,
                  )),
            ),
          ],
        ),
        Row(
          children: [
            Padding(
              padding: EdgeInsets.only(left: 37),
              child: Text("공모가:20,000원 | 상장:8/20 | 주관:키움",
                  style: TextStyle(
                    fontSize: 20,
                  )),
            ),
          ],
        )
      ],
    );
  }
}

1 个答案:

答案 0 :(得分:0)

每次您在有状态小部件中调用 setState 时,您都在调用该小部件的构建方法,并且由于您的 FutureBuilder 是其中的一部分,因此它将被调用。您似乎并没有改变未来,所以我建议您可以将 FutureBuilder 提高一个级别,并将您的有状态小部件放入 FutureBuilder


class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: fetchIPODatas(http.Client()),
        builder: (context, snapshot) {
          //... (add your extracted stateful widget in here..)
        },
      ),
    );
  }
}