skip to Main Content

When the user sign up he type some information then the app navigates to the main screen, the first time I always get LateInitializationError but when I login again to the account no errors, And if I opened on the main screen with the same account also no errors.

class MainScreen extends StatefulWidget {
  MainScreen({
    Key? key,
  }) : super(key: key);

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  String? userID;
  late int age;
  late int weight;
  late int height;
  late int bfp;
  late String gender;
  late String ac;
  late String gl;
  late String disease;
  late var amr;
  late double carb;
  late double protein;
  late double fats;
  late double saturatedFats;
  late double vitaminB12;
  late double vitaminC;
  late double iron;
  late double calcium;
  late double vitaminD;
  late var bmi;
  late var breakfast;
  late var lunch;
  late var dinner;

  late Future<void> _userDataFuture;
  User? user = FirebaseAuth.instance.currentUser;

  List<dynamic> _food = [];
  List<Map<String, dynamic>> _mealPlans = [];

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

    _userDataFuture = _initializeData();
  }

  Future<void> _initializeData() async {
    // To initialize user's data before executing functions
    await getUserData();

    await readJson();

    // Initialize other variables
    amr = await CaloriesUtils.calculateAMR(
      gender: gender,
      age: age,
      weight: weight,
      height: height,
      bfp: bfp,
      ac: ac,
      gl: gl,
    );

    // Calculate nutrition values
    Map<String, double> nutrition = await calculateNutri();
    carb = nutrition['carb'] ?? 0;
    protein = nutrition['protein'] ?? 0;
    fats = nutrition['fats'] ?? 0;

    Map<String, double> diseases = await diseasesControl();
    saturatedFats = diseases['saturatedFats'] ?? 0;
    vitaminB12 = diseases['vitaminB12'] ?? 0;
    vitaminC = diseases['vitaminC'] ?? 0;
    iron = diseases['iron'] ?? 0;
    calcium = diseases['calcium'] ?? 0;
    vitaminD = diseases['vitaminD'] ?? 0;

    await computeMealPlans();
  }

  Map<String, double> calculateNutri() {
    bmi = weight / pow((height / 100), 2);

    Map<String, double> nutrition = NutriUtils.calculateNutri(
      age: age,
      bmi: bmi,
      amr: amr,
      ac: ac,
      gl: gl,
    );

    return nutrition;
  }

  Map<String, double> diseasesControl() {
    Map<String, double> diseases = DiseasesUtils.diseasesControl(
        amr: amr, weight: weight, gender: gender, age: age, diseases: disease);

    return diseases;
  }

  Future getUserData() async {
    try {
      final querySnapshot = await FirebaseFirestore.instance
          .collection('users')
          .where("email", isEqualTo: user?.email)
          .get();

      if (querySnapshot.docs.isNotEmpty) {
        var userData = querySnapshot.docs[0].data();
        setState(() {
          userID = querySnapshot.docs.first.id;
          age = userData['age'].toInt();
          gender = userData['gender'];
          height = userData['height'].toInt();
          weight = userData['weight'].toInt();
          disease = userData['disease'];
          gl = userData['goalWeight'];
          ac = userData['baseLineActivityLevel'];
          if (userData['bfp'] != null) {
            bfp = userData['bfp'];
          } else {
            bfp = 0;
          }
        });
      } else {
        print('User not found for email: ${user?.email}');
      }
    } catch (e) {
      print('Error fetching user data: $e');
    }
  }

  Future<void> readJson() async {
    final String response = await rootBundle.loadString('assets/food.json');
    final data = await json.decode(response);

    setState(() {
      _food = data["food"];
    });
  }

  computeMealPlans() {
    CalculateFood.computeMealPlans(
      food: _food,
      targetProtein: protein,
      targetCarb: carb,
      targetFats: fats,
      diseases: disease,
      callback: (List<Map<String, dynamic>> result) {
        setState(() {
          _mealPlans = result;
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:  FutureBuilder<void>(
          future: _userDataFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              // Display a loading indicator while waiting for the data
              return Center(
                child: CircularProgressIndicator(),
              );
            } else if (snapshot.hasError) {
              return Center(
                child: Text('Error while loading data: ' + snapshot.error.toString()),
              );
            } else if (user == null) {
              return Center(
                child: Text('No user Found'),
              );
            }

            return StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection('users')
                  .doc(userID)
                  .snapshots(),
              builder: (context, snapshot) {
                return Container (
                       // Rest of UI .....
                  )
              },
            );
          }),
    );
  }
}

I tried to sign up a new user after I type my information and the app navigates me to main or home screen the I got I/flutter (23136): Error fetching user data: type 'Null' is not a subtype of type 'String'
form that try block

  Future getUserData() async {
    try {
      final querySnapshot = await FirebaseFirestore.instance
          .collection('users')
          .where("email", isEqualTo: user?.email)
          .get();

      if (querySnapshot.docs.isNotEmpty) {
        var userData = querySnapshot.docs[0].data();
        setState(() {
          userID = querySnapshot.docs.first.id;
          age = userData['age'].toInt();
          gender = userData['gender'];
          height = userData['height'].toInt();
          weight = userData['weight'].toInt();
          disease = userData['disease'];
          gl = userData['goalWeight'];
          ac = userData['baseLineActivityLevel'];
          if (userData['bfp'] != null) {
            bfp = userData['bfp'];
          } else {
            bfp = 0;
          }
        });
      } else {
        print('User not found for email: ${user?.email}');
      }
    } catch (e) {
      print('Error fetching user data: $e');
    }
  }

and the snapshot has error while the screen displays Error while loading data: LateInitializationError: Field ‘bfp’ has not been initialized. from the future builder

2

Answers


  1. Change the late keyword and assign a default value to each variable like this

    int age=0;
    int bfp = 0;
    String gender = "";
    

    or make the variables null-able like this

    int? height;
    int? bfp;
    String? gender;
    

    and then handle the null value when using e.g

    Text(gender ?? "default value")
    
    Login or Signup to reply.
  2. // Inside the FutureBuilder
    return StreamBuilder(
    stream: FirebaseFirestore.instance
    .collection(‘users’)
    .doc(userID)
    .snapshots(),
    builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
    return Center(
    child: CircularProgressIndicator(),
    );
    } else if (snapshot.hasError) {
    return Center(
    child: Text(‘Error while loading data: ${snapshot.error.toString()}’),
    );
    } else if (user == null || age == null || weight == null || height == null) {
    return Center(
    child: Text(‘User data not initialized yet’),
    );
    }

    return Container(
      // Rest of UI .....
    );
    

    },
    );

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search