The method 'contains' was called on null

Viewed 66

Hey guys this is my code: Im trying to display available time slots for my booking app.

   Expanded(
      child: FutureBuilder(
        future: getTimeSlotOfCourt(
          courtModel,
          DateFormat('dd_MM_yyyy').format(context.read(selectedDate).state),
        ),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(
              child: CircularProgressIndicator(),
            );
          } else {
            var listTimeSlot = snapshot.data as List<int>;
            return GridView.builder(
                itemCount: TIME_SLOT.length,
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3),
                itemBuilder: (context, index) => GestureDetector(
                      onTap: listTimeSlot.contains(index)
                          ? null
                          : () {
                              context.read(selectedTime).state =
                                  TIME_SLOT.elementAt(index);
                              context.read(selectedTimeSlot).state = index;
                            },
                      child: Card(
                        color: listTimeSlot.contains(index)
                            ? Colors.white10
                            : context.read(selectedTime).state ==
                                    TIME_SLOT.elementAt(index)
                                ? Colors.white54
                                : Colors.white,
                        child: GridTile(
                          child: Center(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.center,
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Text('${TIME_SLOT.elementAt(index)}'),
                                Text(listTimeSlot.contains(index)
                                    ? 'Full'
                                    : 'Available')
                              ],
                            ),
                          ),
                          header: context.read(selectedTime).state ==
                                  TIME_SLOT.elementAt(index)
                              ? Icon(Icons.check)
                              : null,
                        ),
                      ),
                    ));
          }
        },
      ),
    )
  ],
);

}

I'm getting this error which says the method 'contains' was called on null.

Future<List<int>> getTimeSlotOfCourt(CourtModel courtModel, String date) async {
List<int> result = new List<int>.empty(growable: true);
  // var ref = CourtModel().refer;
  // var bookingRef = ref.collection(date);
  var bookingRef = CourtModel().reference.collection(date);
  QuerySnapshot snapshot = await bookingRef.get();
  snapshot.docs.forEach((element) {
    result.add(int.parse(element.id));
  });
  return result;
}

This is the function that I have used.

Please help me understand why I'm getting this error which says The method 'contains' was called on null.

2 Answers

The snapshot does not always contain data. The Future builder builds once before the future is completed. Null check the snapshot.data and return a spinner or something to fix this problem

The future builder only brings data when the future is completed and the snapshot may not contain data all the time. And you are only checking for the waiting state, a better solution would be to check whether the snapshot has data or not.

Something like this would be the preferred solution.

FutureBuilder(
    future: _getTimeSlotOfCourt(),
    builder:(context, AsyncSnapshot snapshot) {
        if (!snapshot.hasData) {
            return Center(child: CircularProgressIndicator());
         } else {
                 // place you code here  
         }
     }
)
Related