Search code examples
flutterdartgoogle-cloud-firestoredart-null-safety

Flutter Dart - LateInitializationError: Field 'playerSnapshot' has not been initialized


I am creating a blog application and I dont understand why my code is producing the following error:

LateInitializationError: Field 'playerSnapshot' has not been initialized.

See the image attached.

I have tried adding a ? after the late QuerySnapshot? playerSnapshot; but i still recieve errors.

My Current code is:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blog_application/services/crud.dart';
import 'package:flutter_blog_application/views/create_blog.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  CrudMethods crudMethods = new CrudMethods();

  late QuerySnapshot playerSnapshot;


  Widget TransferList(){
    return Container(
      child: Column(
        children: <Widget>[
          playerSnapshot != null
              ? ListView.builder(
              itemCount: playerSnapshot.documents.length,
              itemBuilder: (context, index){
                return PlayerDisplay(
                  playerName: playerSnapshot.documents[index].data['playerName'],
                  fromClub: playerSnapshot.documents[index].data['fromClub'],
                  toClub: playerSnapshot.documents[index].data['toClub'],
                  rumourDesc: playerSnapshot.documents[index].data['rumourDesc'],
                  imgUrl: playerSnapshot.documents[index].data['imgUrl'],
                );
              }) : Container(
                alignment: Alignment.center,
                child: CircularProgressIndicator(),)
          ],
      ),
    );
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    crudMethods.fetchData().then((result){
      playerSnapshot = result;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:AppBar(
        title: Row(
          children: const <Widget>[
          Text(
            "Transfer",
            style: TextStyle(fontSize: 22,  color: Colors.orangeAccent)
          ),
            Text("Blog",
              style: TextStyle(fontSize: 22, color: Colors.black),
            )
        ],
        ),
        backgroundColor: Colors.transparent,
        elevation: 0.0,
      ),
      body: TransferList(),
      floatingActionButton: Container(
        padding: const EdgeInsets.symmetric(vertical: 10),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
          FloatingActionButton(
            onPressed: () {
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => CreateBlog()));
            },
            backgroundColor: Colors.orangeAccent,
            child: const Icon(Icons.add),
          )
        ],),
      ),
    );
  }
}

class PlayerDisplay extends StatelessWidget {

  late String imgUrl, playerName, fromClub, toClub, rumourDesc;
  PlayerDisplay({required String imgUrl,
    required String playerName,
    required String fromClub,
    required String toClub,
    required String rumourDesc});


  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150,
      child: Stack(children: <Widget>[
        ClipRRect(
            borderRadius: BorderRadius.circular(10),
            child: Image.network(imgUrl)),
        Container(
          height: 150,
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.3),
            borderRadius: BorderRadius.circular(10)),
        ),
        Container(child: Column(children: <Widget>[
          Text(playerName),
          Text(fromClub),
          Text(toClub),
          Text(rumourDesc)
        ],),)
      ],),
    );
  }
}

Any help is greatly appreciated!


Solution

  • Instead of using late, make it nullable like

    QuerySnapshot? playerSnapshot;
    

    And call setState

      crudMethods.fetchData().then((result) {
          playerSnapshot = result;
          setState(() {});
        });
    

    Using late promise that value will be assigned before read time, it doesn't make it nullable.

    Also, another thing about reading the querySnapshot. Do it like,

    playerName:
      "${playerSnapshot?.docs[index].get('playerName')}",
     imgUrl: playerSnapshot!.docs[index].get('imgUrl'),
    

    Making nullable is easier to handle null data on runtime.

      String? imgUrl, playerName, fromClub, toClub, rumourDesc;
    

    For image

    if (imgUrl != null)
      ClipRRect(
          borderRadius: BorderRadius.circular(10),
          child: Image.network(imgUrl!)),
    

    And for others text , you can do

     Text(playerName?? "Null"),
    

    You can find more about null-safety