我真的是 Flutter 和 SQLite 的新手。 我需要将从数据库中获取的一些数据存储到全局变量中(在此代码中,它是一个局部变量,仅用于举例),但我不知道:
以下是数据提取的方法
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>>' is not a subtype of type 'List
。
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(),
);
}
}
知道如何解决吗?非常感谢,伙计们。
答案 0 :(得分:1)
从数据库读取是一种异步活动,这意味着查询不会立即返回一些数据。所以你必须等待操作完成,然后将其赋值给一个变量。
DBProvider.instance.openDB(globalConstants.dbName);
List<Map> list = await ObjectRepository.instance.select(DBProvider.instance.database, 'tCars') as List<Map>;
另一方面,您不能在 await
中使用 initState
。
解决方案是创建一个 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;
}
终于可以在initDB
内调用initState
答案 1 :(得分:0)
错误是因为 instant.select
函数返回 Future<List<Map>>
,但您试图将其分配给 List<Map>
,因此您必须等待 future
完成。但 initState
不是 async
函数。因此你不能在那里await
。但是您可以在 future 上使用 then
方法(当 future 完成时调用该值)。并将 callback
(您要使用该值执行的操作)赋予 then 方法。但是在使用 list
语句之前,您必须仔细检查 if
是否为 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
函数根据您给它的未来状态返回适当的 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();
}
)
这是在 Flutter 中更推荐在 UI 中使用期货的方式。