Osian
Osian

Reputation: 180

Flutter does not run Async function

I am trying to get an async function _read() to run and the function does not pass the line: Reading reading = await helper.queryReading(rowId); in this function:

 _read() async {
    DatabaseHelper helper = DatabaseHelper.instance;
    int rowId = 1;
//lines above here executes
    Reading reading = await helper.queryReading(rowId); //this is the line it stops on 
// nothing below here is executed
    if (reading == null) {
      print('read row $rowId: empty');
    } else {
      print('read row $rowId: ${reading.reading}');
    }
  }

It is being called from the following function

class Profile {
  Widget getScreen(){
    print("Attempting to read db");
    _read();

    return  Scaffold( ...)

Here is my helper class:

import 'dart:ffi';
import 'dart:io';
import 'package:ema/Readings.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';

//table structure
final String tableName = 'Readings';
final String databasecolumnId = '_id';
final String databaseReading = 'Reading';
final String databaseDate = 'Time';

class DatabaseHelper {
  //This is the name of the database file on disk
  static final _databaseName = "readings.db";

  //handles versioning for databases
  static final _databaseVersion = 1;

  //makes a singleton classs
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  //allows only one item to access the database
  static Database _database;
  Future<Database> get database async {
    _database = await _initDatabase();
    return database;
  }

  //this opens and creates the database
  _initDatabase() async {
    // The path_provider plugin gets the right directory for Android or iOS.
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    // Open the database. Can also add an onUpdate callback parameter.
    return await openDatabase(path,
        version: _databaseVersion,
        onCreate: _onCreate);
  }



  //Creates the database
Future _onCreate(Database db, int version) async { 
    await db.execute(
        '''
        CREATE TABLE $tableName (
        $databasecolumnId INTEGER PRIMARY KEY,
        $databaseReading REAL NOT NULL,
        $databaseDate INTERGER NOT NULL
        )
        '''
    );
}
Future<int> insertReading(Reading reading) async {
    Database db = await database;
    int id = await db.insert(tableName, reading.toMap());
    return id;

}

//gets reading
Future<Reading> queryReading(int id) async {
    print("queryReading"); //gets here
  Database db = await database;
  print("Getting Db"); // not actually getting here
    List<Map> maps = await db.query(tableName,
        columns: [databasecolumnId, databaseReading, databaseDate],
        where: '$databasecolumnId = ?',
        whereArgs: [id]);
    if (maps.length > 0) {
      return Reading.fromMap(maps.first);
    }
  print('maps length : ${maps.length}');
    return null;
}

}

Here is my Readings class:


class Reading {
  int id;
  double reading;
  DateTime date;

  //constructor
  Reading({this.id, this.reading, this.date});

  Map<String, dynamic> toMap() {
    var map = <String, dynamic>{
      databaseReading: reading,
      databaseDate: date.millisecondsSinceEpoch,
    };
    if (id != null) {
      map[databasecolumnId] = id;
    }
    return map;
  }

  //extracts a node object from the map obect
  Reading.fromMap(Map<String, dynamic> map) {
    id = map[databasecolumnId];
    reading = map[databaseReading];
    date  = new DateTime.fromMillisecondsSinceEpoch(map [databaseDate]);
  }
}

Upvotes: 1

Views: 664

Answers (1)

Osian
Osian

Reputation: 180

Turns out there was a deadlock in getting the database. By putting a lock on it it worked. Here is the code to resolve it:

  ///declreation of the database
  Database _database;

  ///Gets the database ensuring that there are no locks currently on the database
  Future<Database> get database async {
    if (_database != null) return _database;
    _database = await _initDatabase();
    return _database;
  }

Upvotes: 1

Related Questions