Flutter 应用中提供程序与 sqflite 的集成
Posted
技术标签:
【中文标题】Flutter 应用中提供程序与 sqflite 的集成【英文标题】:Provider integration with sqflite in flutter app 【发布时间】:2021-03-04 06:51:56 【问题描述】:我正在尝试实现提供程序模式,但我正在努力将其与 sqflite 数据库集成。 ChangeNotifier 类从数据库中获取字符串列表,然后用 ListView 显示它。我想问题在于,当 ListView 构建小部件时,ChangeNotifier 类尚未初始化列表,因此应用程序崩溃。我该如何解决这个问题?
class FavouritesProvider with ChangeNotifier
List<String> _favourites;
List<String> get favourites => [..._favourites];
FavouritesProvider()
fetchAndSetFav();
Future<void> fetchAndSetFav() async
final data = await DBHelper.instance.getFavourites();
_favourites = data;
@override
Widget build(BuildContext context)
return Scaffold(
body: ChangeNotifierProvider(
create: (_) => FavouritesProvider(),
child: Container (
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.blue[200],
Colors.blue
],
stops: [0.0,1]
)
),
child: Consumer<FavouritesProvider>(
builder: (context, favouritesProvider, child) => ListView.builder (
itemCount: favouritesProvider.favourites.length,
itemBuilder: (context, index)
return Container(
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
width: double.maxFinite,
child: FavouritePositionWidget(key: new Key(index.toString()), streetName: favouritesProvider.favourites[index])
);
,
)
)
)
)
);
这是我得到的错误:
The following NoSuchMethodError was thrown building Consumer<FavouritesProvider>(dirty, dependencies: [_InheritedProviderScope<FavouritesProvider>]):
The getter 'iterator' was called on null.
Receiver: null
Tried calling: iterator
Future<List<String>> getFavourites() async
// Get a reference to the database.
Database db = await DBHelper.instance.database;
List<Map> res = await db.query(table, columns: [columnName]);
List<String> list = [];
for (Map i in res)
var str = i.values.toString();
str=str.substring(1, str.length-1);
list.add(str);
return list;
【问题讨论】:
【参考方案1】:在构建之前您需要await
为fetchAndSetFav()
:
class FavouritesProvider with ChangeNotifier
Future isInitCompleted;
List<String> _favourites;
List<String> get favourites => [..._favourites];
FavouritesProvider()
isInitCompleted = fetchAndSetFav();
Future<void> fetchAndSetFav() async
final data = await DBHelper.instance.getFavourites();
_favourites = data;
还有:
@override
Widget build(BuildContext context)
return Scaffold(
body: ChangeNotifierProvider(
create: (_) => FavouritesProvider(),
child: Container (
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.blue[200],
Colors.blue
],
stops: [0.0,1]
)
),
child: Consumer<FavouritesProvider>(
builder: (context, favouritesProvider, child)
return FutureBuilder(
future: favouritesProvider.isInitCompleted,
builder: (context, snapshot)
if (snapshot.hasData)
return ListView.builder(
itemCount: favouritesProvider.favourites.length,
itemBuilder: (context, index)
return Container(
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
width: double.maxFinite,
child: FavouritePositionWidget(
key: Key(index.toString()),
streetName: favouritesProvider.favourites[index],
)
);
,
)
else
return Center(
child: CircularProgressIndicator(),
);
,
),
)
)
)
);
class DBHelper
static final _databaseName = "FavDatabase.db";
static final _databaseVersion = 1;
static final table = 'favPosition';
static final columnName = 'street';
static final columnNot = 'notification';
DBHelper._privateConstructor();
static final DBHelper instance = DBHelper._privateConstructor();
static Database _database;
Future<Database> get database async
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
_initDatabase() async
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
// SQL code to create the database table
Future _onCreate(Database db, int version) async
await db.execute('''
CREATE TABLE $table (
$columnName TEXT NOT NULL PRIMARY KEY,
$columnNot BIT(1) NOT NULL
)
''');
print("db was created");
Future<void> insertPos(String street) async
final Database db = await database;
final List<Map<String, dynamic>> res = await db.query(table, where: "street = ?", whereArgs: [street]);
if (!res.isNotEmpty)
print("lo deve aggiungere");
Map<String, dynamic> row =
DBHelper.columnName : street,
DBHelper.columnNot : 1,
;
await db.insert(table, row);
else
print("gia aggiunt!");
//Delete a street from the DB
Future<void> deletePos(String street) async
Database db = await DBHelper.instance.database;
await db.delete(table, where: 'street = ?', whereArgs: [street]);
//Update the notification boolean
Future<void> updateNot(String street, bool value) async
// Get a reference to the database.
Database db = await DBHelper.instance.database;
Map<String, dynamic> row =
DBHelper.columnName : street,
DBHelper.columnNot : value?1:0,
;
await db.update(table, row, where: '$DBHelper.columnName = ?', whereArgs: [street]);
//Return a String list of all street's name in the DB
Future<List<String>> getFavourites() async
// Get a reference to the database.
Database db = await DBHelper.instance.database;
List<Map> res = await db.query(table, columns: [columnName]);
List<String> list = [];
for (Map i in res)
var str = i.values.toString();
str=str.substring(1, str.length-1);
list.add(str);
return list;
Future<bool> getNotification(String street) async
// Get a reference to the database.
Database db = await DBHelper.instance.database;
List<Map> res = await db.query(table, columns: [columnNot], where: '$DBHelper.columnName = ?', whereArgs: [street]);
String value = res[0].values.toString();
value = value.substring(1, 2);
if (value == "1")
return true;
else if (value == "0")
return false;
else
throw FormatException("Value can only be 0 or 1");
【讨论】:
我该怎么做? 卡在等待 IsInitCompleted 的未来构建器中DBHelper.instance.getFavourites()
有问题。请显示一些代码。
DBHelper
里面有什么?
对 sqflite 数据库执行操作的函数,但到目前为止它们运行良好以上是关于Flutter 应用中提供程序与 sqflite 的集成的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 中使用 SQFlite 将本地存储的 DB 导出为可读文件
测试 Flutter 本地 sqflite 数据库 onUpgrade 并且应用更新后没有数据显示