FutureBuilder stuck at loading while trying to load data from sqflite

Issue

I’m using sqflite for storing some data. And using a FutureBuilder to display the data after fetching from the database. But the FutureBuilder failing to return data, is always stuck in the loading screen. This is my database code:

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

class HistoryDatabase {
  HistoryDatabase._init();
  static final HistoryDatabase instance = HistoryDatabase._init();
  static Database? _database;

  Future<Database?> get database async {
    if (_database != null) {
      return _database;
    } else {
      _database = await getDatabase();  //loads database
      return _database;
    }
  }

  void deleteHistory() async {  //deletes data
    final db = await instance.database;
    db?.delete('history');
  }

  Future<List<Map<String, dynamic>>> getHistory() async {  //gets database data
    final db = await instance.database;

    print(db?.query('history'));

    return db?.query('history') as List<Map<String, dynamic>>;
  }

  addHistory(String resultExpr, String result) async {  //adds entry
    final db = await instance.database;
    db?.execute(
      'INSERT INTO history (resultExpr, result) VALUES (?, ?)',
      [resultExpr, result],
    );
  }

  Future<Database> getDatabase() async {  //database loader method
    return openDatabase(
      join(await getDatabasesPath(), 'calculator.db'),
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE history(id INTEGER PRIMARY KEY AUTOINCREMENT, resultExpr TEXT NOT NULL, result TEXT NOT NULL)',
        );
      },
      version: 1,
    );
  }
}

This is my FutureBuilder widget:

class _BottomSheetState extends ConsumerState<BottomSheet> {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Map<String, dynamic>>>(
        future: HistoryDatabase.instance.getHistory(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            final history = snapshot.data as List<Map<String, dynamic>>;
            return ListView.builder(
              itemCount: history.length,
              itemBuilder: (context, index) {
                final historyIndex = history[index];
                return ListTile(
                  title: Text(historyIndex['resultExpr'].toString()),
                );
              },
            );
          } else {
            return const Center(
                child: CircularProgressIndicator(  //the futurebuilder always shows this widget
              color: Colors.black,
            ));
          }
        });
  }
}

There’s no error or warnings being shown in my editor. Also I’m sure that there’s no error in the database initialisation, because my insertion method is working perfectly. What’s the mistake I’m making here?

Solution

You are not awaiting for the future here.
Add await in the return statement of getHistory().

Future<List<Map<String, dynamic>>> getHistory() async {
    final db = await instance.database; 
    //add await
    return await db?.query('history') as List<Map<String, dynamic>>;
}

Answered By – R Das

Answer Checked By – Mildred Charles (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.