yogas
yogas

Reputation: 209

how to wait for asynch method completion to load data before build method is called?

i am calling _read method in initState() to read from a file and generate a map. but the method is aynch and it doesnt wait for its completion so map gets null and i get exception 'dataMap passed to pie chart cant be null or empty'. How to wait for the _read() method to complete before loading the widget in build method

import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

class Visualize extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => new VisualizeState();

}

Map<String, double> dataMap = new Map();

class VisualizeState extends State<Visualize> {

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

  @override
  Widget build(BuildContext context) {
      return new Material(
        color: Colors.blueAccent,
        child: new PieChart(
          dataMap: dataMap,
          chartValueBackgroundColor: Colors.blueGrey[900],
          animationDuration: Duration(milliseconds: 800),
          chartLegendSpacing: 32.0,
          chartRadius: MediaQuery
              .of(context)
              .size
              .width / 2.7,
          showChartValuesInPercentage: true,
          showChartValues: true,
        ),
      );
  }

  Future<String> _read() async {
    String text;
    try {
      final Directory directory = await getApplicationDocumentsDirectory();
      final File file = File('${directory.path}/todo_list4.txt');
      text = await file.readAsString();

      var list = text.split("\n");
      for(final x in list)
        {
          var values = x.split(",");
          print(values);
          print(values[0]);
          print(values[1]);
          dataMap.putIfAbsent(values[0], () => double.parse(values[1]) );
        }

    } catch (e) {
      print("Couldn't read file" +e);
    }
    return text;
  }

}

Upvotes: 0

Views: 381

Answers (1)

Karol Lisiewicz
Karol Lisiewicz

Reputation: 674

Use a FutureBuilder for that.

class VisualizeState extends State<Visualize> {
  Future<String> chartDataFuture;

  @override
  void initState()  {
    chartDataFuture = _read();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
      return new FutureBuilder<String>(
        future: chartDataFuture,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            Material(
              color: Colors.blueAccent,
              child: new PieChart(...),
            );
          }
          else {
            // TODO: Build loading or error.
          }
        }
      );
  }

Upvotes: 1

Related Questions