Flutter - LateError (LateInitializationError: Field '_items@68190616' has not been initialized.)

102

Try on initState() create Empty map before using it. because when enter build phase it access to null map which throw error.

  @override
  void initState() {
    _items = <Map<String,dynamic>>[] // Empty one
    _items = _getData(); // Or you can assign it immediately 
    super.initState();
  }

Edit: Try to separate the Initiate from the initState, Because the error that you showed me is that must be Future as await and cast it to the required Type (in this case is List<Map<String, dynamic>>)

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

void _getDataInit() async {
  _items = await _getData() as List<Map<String, dynamic>>;
}

Edit2: After investigation, It turns out there wrong Future implementation. I've add FutureBuilder and removed initState and _items variable to solve the issue and here's the working code (just paste it as form.dart):

import 'database.dart';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:select_form_field/select_form_field.dart';
import 'package:date_time_picker/date_time_picker.dart';

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

  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }
}

class MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  var nameController = TextEditingController();
  var dateController = TextEditingController();
  var courseController = TextEditingController();
  var scoreController = TextEditingController();

  final dateFormat = DateFormat('dd-MM-yyyy');

  final database = Database();

  @override
  void dispose() {
    nameController.dispose();
    dateController.dispose();
    courseController.dispose();
    scoreController.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    bool shouldDisplay = false;

    return Form(
      key: _formKey,
      child: FutureBuilder<List<Map<String, dynamic>>>(
          future: database.getBandits(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            } else {
              if (snapshot.hasError) {
                return ErrorWidget(Exception(
                    'Error occured when fetching data from database'));
              } else if (!snapshot.hasData) {
                return const Center(child: Text('Bandit is empty!'));
              } else {
                return Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 10.0, horizontal: 30.0),
                      child: SelectFormField(
                        controller: nameController,
                        hintText: "...",
                        items: snapshot.data,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return "Hvem er du?";
                          }
                          return null;
                        },
                        decoration: const InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Bandit',
                            prefixIcon: Align(
                              widthFactor: 1.0,
                              heightFactor: 1.0,
                              child: Icon(Icons.person),
                            ),
                            suffixIcon: Align(
                              widthFactor: 1.0,
                              heightFactor: 1.0,
                              child: Icon(Icons.arrow_drop_down),
                            )),
                      ),
                    ),
                    Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 10.0, horizontal: 30.0),
                      child: DateTimePicker(
                        controller: dateController,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            setState(() {
                              dateController.text =
                                  dateFormat.format(DateTime.now()).toString();
                            });
                          }
                          return null;
                        },
                        type: DateTimePickerType.date,
                        dateMask: 'dd-MM-yyyy',
                        firstDate: DateTime(2020),
                        lastDate: DateTime(2050),
                        dateLabelText: 'Dato',
                        decoration: const InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Dato',
                            prefixIcon: Align(
                              widthFactor: 1.0,
                              heightFactor: 1.0,
                              child: Icon(Icons.date_range),
                            )),
                      ),
                    ),
                    Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 10.0, horizontal: 30.0),
                      child: TextFormField(
                        controller: courseController,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            setState(() {
                              courseController.text = "HJGK";
                            });
                          }
                          return null;
                        },
                        decoration: const InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Bane',
                            prefixIcon: Align(
                              widthFactor: 1.0,
                              heightFactor: 1.0,
                              child: Icon(Icons.golf_course),
                            )),
                      ),
                    ),
                    Container(
                        padding: const EdgeInsets.symmetric(
                            vertical: 10.0, horizontal: 30.0),
                        child: TextFormField(
                          controller: scoreController,
                          validator: (value) {
                            if (value == null || value.isEmpty) {
                              return "Indtast score";
                            }
                            return null;
                          },
                          keyboardType: TextInputType.number,
                          decoration: const InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Score',
                            prefixIcon: Align(
                                widthFactor: 1.0,
                                heightFactor: 1.0,
                                child: Icon(Icons.sports_score)),
                          ),
                        )),
                    ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState!.validate()) {
                            _formKey.currentState!.save();
                            shouldDisplay = !shouldDisplay;
                          }
                          shouldDisplay
                              ? showDialog(
                                  context: context,
                                  builder: (context) {
                                    return AlertDialog(
                                      title: const Text("Score registreret"),
                                      content: SingleChildScrollView(
                                        child: ListBody(
                                          children: <Widget>[
                                            Padding(
                                              padding:
                                                  const EdgeInsets.symmetric(
                                                      vertical: 10),
                                              child: Text(
                                                  "Spiller: ${nameController.text}"),
                                            ),
                                            Padding(
                                              padding:
                                                  const EdgeInsets.symmetric(
                                                      vertical: 10),
                                              child: Text(
                                                  "Dato: ${dateController.text}"),
                                            ),
                                            Padding(
                                              padding:
                                                  const EdgeInsets.symmetric(
                                                      vertical: 10),
                                              child: Text(
                                                  "Bane: ${courseController.text}"),
                                            ),
                                            Padding(
                                              padding:
                                                  const EdgeInsets.symmetric(
                                                      vertical: 10),
                                              child: Text(
                                                  "Score: ${scoreController.text}"),
                                            ),
                                          ],
                                        ),
                                      ),
                                      actions: <Widget>[
                                        TextButton(
                                          child: const Text('OK'),
                                          onPressed: () {
                                            Navigator.of(context).pop();
                                          },
                                        ),
                                      ],
                                    );
                                  },
                                )
                              : null;
                        },
                        child: const Text("Submit")),
                  ],
                );
              }
            }
          }),
    );
  }
}
Share:
102
bragi
Author by

bragi

Updated on January 04, 2023

Comments

  • bragi
    bragi over 1 year

    I am fairly new to Flutter and am currently trying to use some data from a database to display in a dropdown select menu (using the mysql1 and select_form_field packages). The SelectFormField needs to be passed a List<Map<String, dynamic>> as its items:-parameter. Whenever I try to run my code I get the exception LateError (LateInitializationError: Field '_items@68190616' has not been initialized.).

    After looking around it seemed like initializing my item list in initState() should do the trick, but I can't get that to work. Below is my main.dart.

    class MyCustomFormState extends State<MyCustomForm> {
      ...
    
      late List<Map<String, dynamic>> _items;
    
      @override
      void initState() {
        _getData();
        super.initState();
      }
    
      _getData() async {
        _items = await getData();
      }
    
      Widget build(BuildContext context) {
    
        return Form(
          key: _formKey,
          child: Column( 
            children: <Widget>[
              Container(
                child: SelectFormField(
                controller: nameController,
                hintText: "...",
                items: _items,
                ...
    }
    

    And this is my database.dart file which is able to fetch and format the data in the List<Map<String, dynamic>> format I need:

    getData() async {
      List<Map<String, dynamic>> items = <Map<String, dynamic>>[];
      dynamic conn = await connect('database');
    
      var results = await conn.query('select * from data');
    
      for (var row in results) {
        items.add({'value': row[0], 'label': row[1]});
      }
    
      await conn.close();
    
      return items;
    }
    

    Any help is greatly appreciated. Thanks!

  • bragi
    bragi about 2 years
    Creating an empty one make the app possible to run, but gives this error as soon as I click the SelectFormField: _AssertionError ('package:flutter/src/material/popup_menu.dart': Failed assertion: line 877 pos 10: 'items != null && items.isNotEmpty': is not true.). Assigning it to _items immediately gives me this error: type 'Future<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>', which was an error I was trying to circumvent with this setup.
  • George Rabbat
    George Rabbat about 2 years
    @simonbrage I have edited the answer to suit the error message. try it and give me your feedback
  • bragi
    bragi about 2 years
    Now if I assign an empty list for starters, _items just remains an empty list. If I assign it immediately, I also have to return _items in _getData(), but in the end I end up with this error again: type 'Future<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>'
  • George Rabbat
    George Rabbat about 2 years
    @simonbrage did you tried after editing and it gives you the same error? it's impossible to be Future<dynamic> because of the await keyword.
  • bragi
    bragi about 2 years
    Ah sorry, I misread it. When I do what you suggest I get the following error in _getDataInit(): _CastError (type 'Null' is not a subtype of type 'List<Map<String, dynamic>>' in type cast)
  • George Rabbat
    George Rabbat about 2 years
    so the main error here is inside _getData() method because it return null. debug it and see what's going on there and why it returns null instead of List
  • bragi
    bragi about 2 years
    Yeah. The odd thing is e.g. if I print(_items) in _getBandits() it will have the data I'm looking for, but if I print(_items) in initState() after my _getBandits(); call, _items will evaluate to null.
  • George Rabbat
    George Rabbat about 2 years
    try to breakpoint the code and follow the code where it gets null. hit me with the result
  • bragi
    bragi about 2 years
    Hmm, if I do breakpoint at _getData() in initState() and step into it, it will show _items as null all the way through. But if I print it from _getData() it will output the correct data.
  • George Rabbat
    George Rabbat about 2 years
    on initState set print(_getData().runtimeType); what the type it gave?
  • bragi
    bragi about 2 years
    It gives Future<dynamic>
  • George Rabbat
    George Rabbat about 2 years
    in my code in the separated method (edited one) put print get data with await with runtime Type. what it yields?
  • bragi
    bragi about 2 years
    If I do print(await _getData().runtimeType in _getDataInit I get this error: NoSuchMethodError (NoSuchMethodError: Class 'Future<dynamic>' has no instance getter 'runtimetype'. Receiver: Instance of 'Future<dynamic>' Tried calling: runtimetype). But I get issues with Future<dynamic> every time I try to return _items from _getData().
  • George Rabbat
    George Rabbat about 2 years
    Try wrap the code like this print((await _getData()).runtimeType)
  • bragi
    bragi about 2 years
    Then it prints List<Map<String, dynamic>>. But it is still null when accessing it in my SelectFormField
  • George Rabbat
    George Rabbat about 2 years
    I have Idea, why don't you use FutureBuilder in your build tree? isn't more efficient? If you have Google Drive please send the code at it to help you
  • George Rabbat
    George Rabbat about 2 years
    @bragi I've Edited the answer try it. it worked for me
  • George Rabbat
    George Rabbat about 2 years
    @bragi Please remove the files from Google Drive for security reasons. And change your Simply.com SQL password. And if it solved you problem accept the answer
  • bragi
    bragi about 2 years
    OMG. Thanks for that shout, was in a hurry yesterday. Your solution works perfectly, thank you very much!
  • George Rabbat
    George Rabbat about 2 years
    @bragi In service. Don't forget to change SQL password
  • bragi
    bragi about 2 years
    Yep, already done. Thanks! :D