How to know whether late init has been initialized in dart(flutter)?

44.3k Views Asked by At

I am fetching data from url in Flutter. I have a late init Map called tables. I am fetching data inside initState() function. When I first launch the app, I am getting LateInizialization error on the red screen. I want to detect whether late init is initialized and display spinner if it is not initialized. This is my code.

class TablesTab extends StatefulWidget {
  @override
  _TablesTabState createState() => _TablesTabState();
}

class _TablesTabState extends State<TablesTab> {
  late List<dynamic> tables;
  var refreshKey = GlobalKey<RefreshIndicatorState>();
  GetUriData tablesInstance = new GetUriData(url: '/api/table/getAllTables');

  void getTables() async {
    tables = await tablesInstance.getData();
  }

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

  Future<void> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    // await Future.delayed(Duration(seconds: 2));
    var updatedTables = await tablesInstance.getData();
    setState(() {
      tables = updatedTables;
    });

    //network call and setState so that view will render the new values
    print(tables);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: RefreshIndicator(
          child:  GridView.count(
            crossAxisCount: 4,
            children: List.generate(this.tables.length, (index) {
              return Center(
                child: GestureDetector(
                  onTap: () {
                    Navigator.pushNamed(context, '/tableReview', arguments: {'table': this.tables[index]});
                  },
                  child: Container(
                      width: 80,
                      height: 80,
                      decoration: BoxDecoration(
                          border: Border.all(color: Theme.of(context).primaryColor, width: 2.0),
                          borderRadius: BorderRadius.all(Radius.circular(70))
                      ),
                      padding: const EdgeInsets.all(14.0),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          Text(
                            '${this.tables[index]['tableNum']}',
                            style: TextStyle(
                                color: Theme.of(context).primaryColor,
                                fontSize: 23
                            ),
                          ),
                        ],
                      )
                  ),
                ),
              );
            }),
          ),
          onRefresh: refreshList
      )
    );
  }
5

There are 5 best solutions below

0
On

You can give any default value in the constructor if you are using late initializer or you can make them nullable but making nullable is hectic

2
On

You can't check the initialization state of a late variable. If that's something you need to know, you either will need to add and maintain a separate flag or make the variable nullable and compare to null instead.

I want to detect whether late init is initialized and display spinner if it is not initialized.

In your case you probably should use a FutureBuilder.

2
On

You can't know whether late field initialized or not.

I don't think you should use late in that case. Adding late to field means that the field will be initialized when you use it for the first time. In your code the field can be not initialized, so you'd better to use tables without late, initialize it with empty list and use boolean flag to indicate loading:

  var tables = [];
  var loading = false;

  ...

  Future<void> refreshList() async {
    ...
    setState(() {
      loading = true;
    });
    var updatedTables = await tablesInstance.getData();
    setState(() {
      tables = updatedTables;
      loading = false;
    });
    ...
  }
0
On

I think I found the answer, in my case, it is not about the mapController, it is about size I added Flexible as parent of FlutterMap and map showing perfect

Try below code:

Flexible(
  child: FlutterMap(
    options: MapOptions(
      center: LatLng(51.5, -0.09),
      zoom: 5.0,
    ),
    layers: [
      TileLayerOptions(
        urlTemplate:
            'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        subdomains: ['a', 'b', 'c'],
        tileProvider:
            NonCachingNetworkTileProvider(),
      ),
      MarkerLayerOptions(markers: [])
    ],
  ),
),
0
On

You can.

class MyClass {
  late double myLateField;
  bool _isInitialized = false;

  void myFunction() {
    if (!_isInitialized) {
      _isInitialized = true;
      // ... init your late field.
    }
  }

}

As others have said, you probably shouldn't do this. But technically, it's possible with this workaround.