'Future<List>' 类型的值不能分配给 'List' 类型的变量

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

我真的是 Flutter 和 SQLite 的新手。 我需要将从数据库中获取的一些数据存储到一个全局变量中(在这段代码中它是一个局部变量,只是为了举例)我不知道:

  1. 我能做的最好的地方在哪里(现在我把它放在首页的initState方法中);
  2. 我如何将未来的数据存储在一个没有未来的变量中。

下面是数据提取的方法

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;
  }
}

下面是我将 future> 放入 List 的位置(我知道我不能,事实上 IDE 给了我这个错误 A类型 'Future<List<Map<dynamic, dynamic>>>' 的值无法分配给类型 'List<Map<dynamic, dynamic>>' 的变量。请尝试更改变量的类型,或将右侧类型强制转换为 'List<Map<dynamic, dynamic>>' .

我什至尝试转换它,但我在 运行 时遇到了类似的问题 "type 'Future<List<Map<dynamic, dynamic>>>' is not a subtype of type 'List<Map<dynamic, dynamic>>' in类型转换".

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(),
    );
  }
}

知道如何解决吗?非常感谢,伙计们。

从数据库读取是异步的activity,这意味着查询不会立即return一些数据。所以你必须等待操作完成,然后将其分配给一个变量。

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

另一方面,您不能在 initState 中使用 await。 解决方案是创建一个 async 函数来处理从数据库获取数据的过程。

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;
}

终于可以在 initState

中调用 initDB

错误是因为 instant.select 函数 return 是 Future<List<Map>> 但你试图将它分配给 List<Map> 因此你必须等待 [=15= 】 完成。但是 initState 不是 async 函数。因此你不能在那里await。但您可以在 future 上使用 then 方法(当 future 完成时调用该方法)。然后给它 callback (你想用这个值执行的动作)到 then 方法。但在使用 if 语句之前,您必须仔细检查 list 是否为 null,因为它最初设置为 null。

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

如果您想要将列表用于小部件(例如:ListView),请执行此操作。考虑使用 FutureBuilder,它采用 futurebuilder 函数,根据您赋予它的未来状态 return 适当 widget。例如,

 FutureBuilder<List<Map>>(
   future: ObjectRepository.instance.select(DBProvider.instance.database, 'tCars') // your future here,
builder : (context, snapshot) {
       if (snapshot.hasError) return ErorrScreen();
       if (snapshot.hasData) return ListView.builder(itemCount :  snapshot.data.length,
         itemBuilder: (context, index) {
             return Text(snpshot.data[index].toString());
});
return CicularProgressIndicator();
}
)

这是更推荐的在你的 UI in flutter 中使用 futures 的方式。