Flutter: Database being accessed too quickly

Viewed 46

This is a pretty basic question but I am stuck and would appreciate any assistance.

I am using a Hive database and have a condition to check if the database is empty. If it is empty, I have a function to copy another database to it. But the database is being called before the copy is complete resulting in a RangeError: 0. How do I make it wait until the copy is complete before accessing it?

Calling Code

    Box db = Hive.box<CardFields>("starter_worker");
    dbcheck(db);
    int currentcardindex = randomcard(db); // Function to generate random index based on db length
    CardFields currentCard = db.getAt(currentcardindex);

dbcheck()

dbcheck(Box db) async {
    if (db.isEmpty) {
      await refilldb("starter");
    }
  }

refilldb()

refilldb(String db) async {
  Directory devicedir = await getApplicationDocumentsDirectory();
  var workerpath = join(devicedir.path + "/db/" + db + "_worker.hive");
  var statpath = join(devicedir.path + "/db/" + db + ".hive");
  if (File(workerpath).existsSync() == false) {
    new File(workerpath).create(recursive: true);
  }
  await File(statpath).copy(workerpath);
}

UPDATED CODE

class _StarterCardState extends State<StarterCard> {
  String contentString = "";
  String tempString = "";
  String tempString1 = "";
  List randplayers = [];
  String player1 = "";
  String player2 = "";
  String player3 = "";

  Box db = Hive.box<CardFields>("starter_worker");

  Future<dynamic> dbCheck(Box db) async {
    if (db.isEmpty) {
      await refilldb("starter");
    }
  }

  @override
  Widget build(BuildContext context) {
    int currentcardindex = randomcard(db);
    CardFields currentCard = db.getAt(currentcardindex);

    randplayers = players;
    randplayers.shuffle();
    player1 = randplayers.elementAt(0);
    player2 = randplayers.elementAt(1);
    player3 = randplayers.elementAt(2);

    if (currentCard.content.contains("\$player1")) {
      tempString = currentCard.content.replaceAll("\$player1", "$player1");
      tempString1 = tempString.replaceAll("\$player2", "$player2");
      contentString = tempString1.replaceAll("\$player3", "$player3");
    } else {
      contentString = currentCard.content;
    }
    db.deleteAt(currentcardindex);

    return FutureBuilder<dynamic>(
        future: dbCheck(db),
        initialData: "Loading...",
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return CircularProgressIndicator();
          }
          if (snapshot.connectionState == ConnectionState.done) {
            return Expanded(
              flex: 1,
              child: Container(
                width: double.infinity,
                color: Colors.blueAccent,
                child: Column(
                  children: [
                    Text("$contentString"),
                  ],
                ),
              ),
            );
          }
          return Container();
        });
  }
}
2 Answers

You should try to await your dbcheck function.

await dbcheck(db);

"too quickly" can't be something a developer faces.. you must await for async methods and calls..

in the build method you have to use a FutureBuilder in order to await for the execution of a function. inside the builder you can check the state of your data so you can display a loading widget before your data is ready

Related