#flutter #flutter-provider #sqflite
#flutter #flutter-провайдер #sqflite
Вопрос:
Я пытаюсь реализовать шаблон поставщика, но мне трудно интегрировать его с базой данных 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");
}
}
}
Комментарии:
1. Как я могу это сделать?
2. Он застревает в сборщике будущего, ожидая завершения IsInitCompleted
3. Что-то не так с
DBHelper.instance.getFavourites()
. Покажите, пожалуйста, какой-нибудь код.4. Что внутри
DBHelper
?5. функции для выполнения операций с базой данных sqflite, но до сих пор они работали отлично