Singorenko
Singorenko

Reputation: 513

How to get data from firestore and refresh the state automatically without click in flutter

I am working with the calendar carousel widget and I'm trying to add events from cloud firestore. I am successful getting the date from firebase, the problem is that is only visible after a click on any date, so when the user looks for the first time the calendar there is no information about the events from the server side. The screen is also refreshed if I go back to the parent, and return to the calendar. How could I refresh the data on the calendar? I was looking over the web and only found examples using ListViews.

Only when I click on a button the firebase data is shown. (Or when back to the parent and return) as is seen in the gif.

Only when I click on a button the firebase data is shown

import 'package:flutter/material.dart';
import 'package:father_home_flutter/model/constants.dart';
import 'package:flutter_calendar_carousel/classes/event.dart';
import 'package:flutter_calendar_carousel/classes/event_list.dart';
import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'
    show CalendarCarousel;
import 'package:cloud_firestore/cloud_firestore.dart';

class ScreenCalendar extends StatefulWidget {
  @override
  _ScreenCalendarState createState() => new _ScreenCalendarState();
}

class _ScreenCalendarState extends State<ScreenCalendar> {
  static String noEventText = "Событий нет";
  String tabBarTitle = "Calendar";
  String calendarText = noEventText;
  DateTime _currentDate = DateTime.now();
  Color _colorButtonColor = Colors.indigo;
  Color _colorTextButtonColor = Colors.black;
  Color _colorTextTodayButton = Colors.white;

  static const String _calendarRussian = "calendarRussian";
  static const String _eventTitle = "eventTitle";

  static const String _eventDay = "eventDay";
  static const String _eventMonth = "eventMonth";
  static const String _eventYear = "eventYear";

  void getCalendarEventList() {
    Firestore.instance.collection(_calendarRussian).snapshots().listen((data) =>
        data.documents.forEach((doc) => _markedDateMap.add(
                new DateTime(int.parse(doc[_eventYear]),
                    int.parse(doc[_eventMonth]), int.parse(doc[_eventDay])),
                new Event(
                    date: new DateTime(int.parse(doc[_eventYear]),
                        int.parse(doc[_eventMonth]), int.parse(doc[_eventDay])),
                    title: doc[_eventTitle],
                    icon: _eventIcon))
//            context.setState(() => refresh(DateTime.now()))}
            ));
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(
            tabBarTitle,
            style: Constants.myTextStyleAppBar,
          ),
          iconTheme: Constants.myIconThemeDataAppBar,
          elevation: Constants.myElevationAppBar,
          backgroundColor: Constants.myAppBarColor,
        ),
        body: SingleChildScrollView(
            child: Column(children: <Widget>[
          Card(
              child: CalendarCarousel(
            weekendTextStyle: TextStyle(
              color: Colors.red,
            ),
            weekFormat: false,
            selectedDateTime: _currentDate,
            markedDatesMap: _markedDateMap,
            selectedDayBorderColor: Colors.transparent,
            selectedDayButtonColor: Colors.indigo[300],
            todayTextStyle:
                TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
            selectedDayTextStyle: TextStyle(color: _colorTextButtonColor),
            todayBorderColor: Colors.indigo,
            weekdayTextStyle: TextStyle(color: Colors.black),
            height: 420.0,
            daysHaveCircularBorder: true,
            todayButtonColor: Colors.transparent,
            locale: 'RUS',
            onDayPressed: (DateTime date, List<Event> events) {
              this.setState(() => refresh(date));
            },
          )),
          Card(
              child: Container(
                  child: Padding(
                      padding: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0),
                      child: Center(
                          child: Text(
                        calendarText,
                        style: Constants.textStyleCommonText,
                      )))))
        ])));
  }

  void refresh(DateTime date) {
    _currentDate = date;
    print('selected date ' +
        date.day.toString() +
        date.month.toString() +
        date.year.toString() +
        ' ' +
        date.toString());
    if (_markedDateMap
        .getEvents(new DateTime(date.year, date.month, date.day))
        .isNotEmpty) {
      calendarText = _markedDateMap
          .getEvents(new DateTime(date.year, date.month, date.day))[0]
          .title;
    } else {
      calendarText = noEventText;
    }
    if (date == _currentDate) {
      _colorButtonColor = Colors.indigo;
      _colorTextButtonColor = Colors.white;
      _colorTextTodayButton = Colors.white;
    } else {
      _colorTextButtonColor = Colors.indigo;
      _colorTextTodayButton = Colors.black;
    }
  }
}

EventList<Event> _markedDateMap = new EventList<Event>(events: {
  new DateTime(2019, 1, 24): [
    new Event(
      date: new DateTime(2019, 1, 24),
      title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, '
          'sed eiusmod tempor incidunt ut labore et dolore magna aliqua.'
          ' \n\nUt enim ad minim veniam,'
          ' quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.'
          ' \n\nQuis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. '
          'Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
      icon: _eventIcon,
    )
  ]
});

Widget _eventIcon = new Container(
  decoration: new BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.all(Radius.circular(1000)),
      border: Border.all(color: Colors.blue, width: 2.0)),
  child: new Icon(
    Icons.person,
    color: Colors.amber,
  ),
);

Upvotes: 0

Views: 4136

Answers (1)

Singorenko
Singorenko

Reputation: 513

Ok, I found a way to solve it using async and await, this is the part of the code I changed.

  Future<void> getCalendarEventList() async {
    await Firestore.instance.collection(_calendarRussian).snapshots().listen(
        (data) => data.documents.forEach((doc) => _markedDateMap.add(
            new DateTime(int.parse(doc[_eventYear]),
                int.parse(doc[_eventMonth]), int.parse(doc[_eventDay])),
            new Event(
                date: new DateTime(int.parse(doc[_eventYear]),
                    int.parse(doc[_eventMonth]), int.parse(doc[_eventDay])),
                title: doc[_eventTitle],
                icon: _eventIcon))));
    setState(() {});
  }

and to avoid the duplicate of calendar events I decided to clean the marketDataMap:

  @override
  void dispose(){
    _markedDateMap.clear();
    super.dispose();
  }

Upvotes: 3

Related Questions