'Future<List>' 类型的值不能分配给 'List' 类型的变量
A value of type 'Future<List>' can't be assigned to a variable of type 'List'
我真的是 Flutter 和 SQLite 的新手。
我需要将从数据库中获取的一些数据存储到一个全局变量中(在这段代码中它是一个局部变量,只是为了举例)我不知道:
- 我能做的最好的地方在哪里(现在我把它放在首页的initState方法中);
- 我如何将未来的数据存储在一个没有未来的变量中。
下面是数据提取的方法
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
我什至尝试转换它,但我在 运行 时遇到了类似的问题 "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
,它采用 future
和 builder
函数,根据您赋予它的未来状态 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 的方式。
我真的是 Flutter 和 SQLite 的新手。 我需要将从数据库中获取的一些数据存储到一个全局变量中(在这段代码中它是一个局部变量,只是为了举例)我不知道:
- 我能做的最好的地方在哪里(现在我把它放在首页的initState方法中);
- 我如何将未来的数据存储在一个没有未来的变量中。
下面是数据提取的方法
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
我什至尝试转换它,但我在 运行 时遇到了类似的问题 "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
,它采用 future
和 builder
函数,根据您赋予它的未来状态 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 的方式。