A value of type 'Future<List>' can't be assigned to a variable of type 'List'

3,317

Reading from database is an asynchronous activity, which means the query doesn't return some data immediately. so you have to wait for the operation to complete and then assign it to a variable.

DBProvider.instance.openDB(globalConstants.dbName);
List<Map> list = await ObjectRepository.instance.select(DBProvider.instance.database, 'tCars') as List<Map>;

On the other hand, you can not use await inside initState. The solution is to create an async function that handles the process of getting data from database.

Future<List<Map>> initDB()async{
  DBProvider.instance.openDB(globalConstants.dbName);
  List<Map> list = await ObjectRepository.instance.select(DBProvider.instance.database, 'tCars') as List<Map>;
  return list;
}

finally you can call initDB inside initState

Share:
3,317
oldredman
Author by

oldredman

Updated on December 30, 2022

Comments

  • oldredman
    oldredman over 1 year

    I am really newbie in Flutter and SQLite. I need to store some data got from a DB into a global variable (in this code it's a local variable just for exemplification) and I don't know:

    1. where is the best point I can do it (now I put it in the homepage's initState method);
    2. how I can store future data in a no-future variable.

    Below is the method for the data extraction

    class ObjectRepository {
      ObjectRepository._(); 
      static final ObjectRepository instance = ObjectRepository._();
    
      Future<List<Map>> select(Database db, String tableName, {List<String> fields}) async {
            sql = 'SELECT ' + (fields != null ? fields.toString() : '* ');
            sql = sql + 'FROM $tableName';
        
            final List<Map> list = await db.rawQuery(sql);
        
            return list;
      }
    }
    

    Below is where I put my future<List<Map>> into a List<Map> (I know I can't, in fact the IDE gives me this error A value of type 'Future<List<Map<dynamic, dynamic>>>' can't be assigned to a variable of type 'List<Map<dynamic, dynamic>>'. Try changing the type of the variable, or casting the right-hand type to 'List<Map<dynamic, dynamic>>'.

    I even tried to cast it, but I got a similar issue at run-time "type 'Future<List<Map<dynamic, dynamic>>>' is not a subtype of type 'List<Map<dynamic, dynamic>>' in type cast".

    class HomePage extends StatefulWidget {
      HomePage({Key key}) : super(key: key);
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      void initState() {
        super.initState();
    
        DBProvider.instance.openDB(globalConstants.dbName);
        List<Map> list = ObjectRepository.instance.select(DBProvider.instance.database, 'tCars') as List<Map>;
      }
    
      @override
      void dispose() {
        DBProvider.instance.closeDB();
    
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: CustomAppBar(title: Text('Cars')),
          drawer: CustomDrawer(),
          body: CustomBody(),
        );
      }
    }
    

    Any idea how can I resolve it? Many thanks, folks.

    • Randal Schwartz
      Randal Schwartz almost 3 years
      It's a Future. You have to await it somewhere. Don't be in such a hurry. :)
  • oldredman
    oldredman almost 3 years
    On the other hand, you can not use await inside initState. The solution is to create an async function that handles the process of getting data from database. Finally you can call initDB inside initState This works for me: simple, effective for a newbie like me. Thank you!