How to load data on app start from file with Flutter and sqflite? - flutter

I have a whole list of data I want to load into my app when it starts up. I was able to extract into a JSON file so I can load it into my table, but it's not quite loading correctly and also seems to get added multiple times. It looks like I am loading in the file correctly via assets (printing the values in _loadIngredients gives me the right results). But when it is saved into the DB, it just gets saved as an integer and that is what shows up in the view.
I could not find a good example of this anywhere.
Where am I going wrong?
In my DatabaseHandler:
class DatabaseHandler{
DatabaseHandler._();
static final DatabaseHandler db = DatabaseHandler._();
static DatabaseHandler get() {
return db;
}
static Database _database;
final databaseName = "recipe.db";
DatabaseHandler._createInstance();
Future<Database> get database async {
if (_database != null)
return _database;
_database = await initDB();
return _database;
}
initDB() async {
var path = await getDatabasesPath();
print("Creating tables at path: $path");
var dbPath = join(path, 'recipe.db');
Database dbConnection = await openDatabase(dbPath, version: 1,
onCreate: (Database db, int version) async {
return db.execute(
"CREATE TABLE ingredients(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
);
}
);
await _loadIngredients(dbConnection);
return dbConnection;
}
_loadIngredients(Database db) async {
Batch batch = db.batch();
List<Map<String, dynamic>> records = await db.query('ingredients');
print(records);
String ingredientsJson = await rootBundle.loadString('assets/json/ingredients.json');
List ingredientsList = json.decode(ingredientsJson);
ingredientsList.forEach((val) {
print(val);
Ingredient ingredient = Ingredient.fromMap(val);
batch.insert("ingredients", ingredient.toMap(false));
});
var results = await batch.commit();
}
}
My ingredient class:
class Ingredient {
int id;
String name;
String categoryName;
DateTime dateCreated;
Ingredient(this.id, this.name, this.categoryName, this.dateCreated);
Map<String, dynamic> toMap(bool forUpdate) {
if(dateCreated == null) {
dateCreated = new DateTime.now();
}
var data = {
// 'id': id, since id is auto incremented in the database we don't need to send it to the insert query.
'name': utf8.encode(name),
'category_name': utf8.encode(categoryName),
'date_created': epochFromDate( dateCreated )
};
if(forUpdate){
data["id"] = this.id;
}
return data;
}
Ingredient.fromMap(Map map){
id = map["id"];
name = map["name"];
categoryName = map["category_name"];
dateCreated = map["date_created"];
}
// Converting the date time object into int representing seconds passed after midnight 1st Jan, 1970 UTC
int epochFromDate(DateTime dt) {
return dt.millisecondsSinceEpoch ~/ 1000 ;
}
// overriding toString() of the note class to print a better debug description of this custom class
#override toString() {
return {
'id': id,
'name': name,
'category_name': categoryName,
'date_created': epochFromDate( dateCreated )
}.toString();
}
}
My homepage class where I am initializing my DB:
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Map<String, dynamic>> _allIngredientsInQueryResult = [];
var notesViewType ;
#override void initState() {
super.initState();
notesViewType = viewType.Staggered;
DatabaseHandler.db.initDB();
retrieveAllIngredientsFromDatabase();
}
#override
Widget build(BuildContext context) {
return
Container(
child: _ingredientList()
);
}
Widget _ingredientList() {
return Container(
child: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: _allIngredientsInQueryResult.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[100],
child: Center(child: Text('Entry ${_allIngredientsInQueryResult[index]["name"]}')),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
);
}
retrieveAllIngredientsFromDatabase() async {
var _testData = await DatabaseHandler.db.selectAllIngredients();
setState(() {
_allIngredientsInQueryResult = _testData;
});
}
}
Image of what I am seeing in the app:
Ingredients json

if you use utf8.encode(name), you convert your String in bytes something like flour = [102, 108, 111, 117, 114]
and when you display this values you must also set a utf8.decode(map["name"])
in your example something like
Text('Entry ' + utf8.decode(${_allIngredientsInQueryResult[index]["name"]})))
every time your initDB() is calling, the Data comes again in the DB. You can do it only in the onCreate part of the Sqlite DB
initDB() async {
var path = await getDatabasesPath();
print("Creating tables at path: $path");
var dbPath = join(path, 'recipe.db');
Database dbConnection = await openDatabase(dbPath, version: 1,
onCreate: (Database db, int version) async {
await db.execute(
"CREATE TABLE ingredients(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, category_name TEXT, date_created INTEGER)",
);
await _loadIngredients(db);
}
);
return dbConnection;
}
i would also use your model class and not a dynimac map
Define _allIngredientsInQueryResult
List<Ingredient> _allIngredientsInQueryResult = new List();
get selectAllIngredients, with the fromMap()
Future<List<Ingredient>> selectAllIngredients() async {
var dbClient = await database;
List<Map> result = await dbClient.query('ingredients');
List<Ingredient> r_ingredient = result.map((i) => Ingredient.fromMap(i)).toList();
return r_ingredient;
}
set Decode in the fromMap()
Ingredient.fromMap(Map map){
id = map["id"];
name = utf8.decode(map["name"]);
categoryName = utf8.decode(map["category_name"]);
dateCreated = DateTime.fromMillisecondsSinceEpoch(map["date_created"]);
}
get Ingredients
retrieveAllIngredientsFromDatabase() async {
DatabaseHandler.db.selectAllIngredients().then((List<Ingredient> r_ingredient) {
setState(() {
_allIngredientsInQueryResult = r_ingredient;
});
});
}
display in the Listview
Text('Entry ' + _allIngredientsInQueryResult[index].name)

Related

How toGet data from api and save it into local database sqlite then show in listview (from local)

How to get data from api and save the data to locally database sqlite?
this is my code, but still got error in dio
can you guys help me
error dio
import 'package:bloggggg/employee_model.dart';
import 'package:bloggggg/db_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';
class EmployeeApiProvider {
Future<List<Employee?>> getAllEmployees() async {
final url = "http://demo8161595.mockable.io/employee";
Response response = await Dio().get(url);
if(response.statusCode == 200){
return (response.data as List).map((employee) {
print('Inserting $employee');
DBProvider.db.createEmployee(Employee.fromJson(employee));
}).toList();
}else{
return response.data;
}
}
}
Save Api Data Function
save() async {
final dbHelper = DatabaseHelper.instance;
const url = "http://demo8161595.mockable.io/employee";
final result = await get(Uri.parse(url));
final response = jsonDecode(result.body);
Map<String, dynamic> row = DatabaseInsetItemModel(
name: response["name"] ?? "",
lName: response["lName"] ?? "",
mobile: response["mobile"] ?? "",
email: response["email"] ?? "",
cat: response["cat"] ?? "",
profile: response["profile"] ?? "")
.toJson();
print('insert stRT');
final id = await dbHelper.insertContact(row);
if (kDebugMode) {
print('inserted row id: $id');
}
}
DataBase Helper
class DatabaseHelper {
static final _databaseName = "MyDatabase.db";
static final _databaseVersion = 1;
static final table = 'category';
static final tableContact = 'contact';
static final columnId = '_id';
static final columnName = 'name';
static final columnLName = 'lname';
static final columnMobile = 'mobile';
static final columnEmail = 'email';
static final columnCategory = 'cat';
static final columnProfile = 'profile';
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// only have a single app-wide reference to the database
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database?> get database1 async {
if (_database == null) {
_database = await _initDatabase();
}
return _database;
}
// this opens the database (and creates it if it doesn't exist)
_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 (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL
)
''');
await db.execute('''
CREATE TABLE $tableContact (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnLName TEXT NOT NULL,
$columnMobile TEXT NOT NULL,
$columnEmail TEXT NOT NULL,
$columnCategory TEXT NOT NULL,
$columnProfile TEXT NOT NULL
)
''');
}
// Helper methods
// Inserts a row in the database where each key in the Map is a column name
// and the value is the column value. The return value is the id of the
// inserted row.
Future<int> insert(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db.insert(table, row);
}
Future<int> insertContact(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db.insert(tableContact, row);
}
// All of the rows are returned as a list of maps, where each map is
// a key-value list of columns.
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
Future<List<Map<String, dynamic>>> queryAllRowsofContact() async {
Database db = await instance.database;
return await db.query(tableContact);
}
// All of the methods (insert, query, update, delete) can also be done using
// raw SQL commands. This method uses a raw query to give the row count.
Future<int> queryRowCount() async {
Database db = await instance.database;
return Sqflite.firstIntValue(
await db.rawQuery('SELECT COUNT(*) FROM $table')) ??
0;
}
// We are assuming here that the id column in the map is set. The other
// column values will be used to update the row.
Future<int> update(Map<String, dynamic> row) async {
Database db = await instance.database;
int id = row[columnId];
return await db.update(table, row, where: '$columnId = ?', whereArgs: [id]);
}
// Deletes the row specified by the id. The number of affected rows is
// returned. This should be 1 as long as the row exists.
Future<int> delete(int id) async {
Database db = await instance.database;
return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
}
Future<int> deleteContact(int id) async {
Database db = await instance.database;
return await db.delete(tableContact, where: '$columnId = ?', whereArgs: [id]);
}
}
DataBase Item Model
class DatabaseInsetItemModel{
String? name;
String? lName;
String? mobile;
String? email;
String? cat;
String? profile;
DatabaseInsetItemModel(
{required this.name, required this.lName, required this.mobile, required this.email, required this.cat, required this.profile});
DatabaseInsetItemModel.fromJson(Map<String, dynamic> json) {
name = json['postId'];
lName = json['id'];
mobile = json['name'];
email = json['email'];
cat = json['body'];
profile = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data[DatabaseHelper.columnName] = name;
data[DatabaseHelper.columnLName] = lName;
data[DatabaseHelper.columnMobile] = mobile;
data[DatabaseHelper.columnEmail] = email;
data[DatabaseHelper.columnCategory] = cat;
return data;
}
}
Show Data on screen
class ShowPostScreen extends StatefulWidget {
ShowPostScreen({Key? key}) : super(key: key);
#override
State<ShowPostScreen> createState() => _ShowPostScreenState();
}
class _ShowPostScreenState extends State<ShowPostScreen> {
final dbHelper = DatabaseHelper.instance;
List<DatabaseInsetItemModel> data = [];
#override
void initState() {
// TODO: implement initState
dbHelper.queryAllRows().then((value) {
setState(() {
data = value.map((e) => DatabaseInsetItemModel.fromJson(e)).toList();
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Text(data[index].name ?? "");
},
),
);
}
}

Data in SQLflite database is not deleting, in my Flutter project

So I have an issue of data not being deleted from my database. It is supposed to happen when a dismissible widget is swiped away.
This is the model class:
class DateModel {
//define schema
int? id;
final String dateText;
DateModel({this.id, required this.dateText});
//convert json data to DateModel instance
factory DateModel.fromMap(Map<String, dynamic> json) {
return DateModel(id: json["id"], dateText: json["dateText"]);
}
//convert DateModel instance to json
Map<String, dynamic> toMap() => {"id": id, "dateText": dateText};
}
Below is where some CRUD operations are defined. I concluded that the error is because I'm not properly storing the id upon insert (in the "add" function). Although I'm not certain I'm doing this right.
class DatabaseHelper {
static Database? _db;
//create singleton
DatabaseHelper._constructor();
static final DatabaseHelper instance = DatabaseHelper._constructor();
Future<Database> get db async {
return _db ??= await init_db("Date.db");
}
//create database when it doesn't exist
Future<Database> init_db(String name) async {
//locate database
var databasePath = await getDatabasesPath();
String path = join(databasePath, name);
//open database and return
return await openDatabase(path, version: 1, onCreate: _onCreate);
}
//Create date table
Future _onCreate(Database db, int version) async {
await db
.execute("CREATE TABLE Dates (id INTEGER PRIMARY KEY, dateText TEXT)");
}
//add user input to table
Future<int> add(DateModel dateModel) async {
Database db = await instance.db;
//store id of inserted date (generated by db.insert method)
final id = await db.insert("Dates", dateModel.toMap());
return dateModel.id = id;
}
//remove date from table
Future<int> remove(int id) async {
Database db = await instance.db;
return await db.delete("Dates", where: "id = ?", whereArgs: [id]);
}
Future<List> getDates() async {
Database db = await instance.db;
final data = await db.rawQuery("SELECT dateText FROM Dates");
if (data.isNotEmpty) {
return data;
} else {
return [];
}
}
}
And lastly, this is where the delete action is supposed to take place (in dismissible's onDismissed property):
Widget build(BuildContext context) {
return Consumer<Date>(builder: (context, date, child) {
return Scaffold(
body: FutureBuilder(
future: DatabaseHelper.instance.getDates(),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
if (!snapshot.hasData || snapshot.connectionState != ConnectionState.done) {
return CircularProgressIndicator();
}
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return SlideTransition(
position:
Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0))
.animate(CurvedAnimation(
parent: _controller, curve: Curves.bounceIn)),
child: Dismissible(
key: UniqueKey(),
direction: DismissDirection.horizontal,
onDismissed: (direction) async {
final dateModel =
DateModel(dateText: date.dateList[index]);
//remove from list
date.dateList.removeAt(index);
//remove from database
await DatabaseHelper.instance.remove(dateModel.id!);
},
child: ListTile(title: Text(snapshot.data![index].toString()))),
);
});
},
),
);
});
}
I get the error that I'm doing a null check on a null value, which I believe is the dateModel.id.
I tried storing the id upon insert a couple of different ways. Nothing changed.
This is because you are trying to do exactly that: Putting a null check operator on a null value.
You are creating the dateModel like this:
final dateModel = DateModel(dateText: date.dateList[index]);
You do not pass any value for the id, which then is null.
Try something like this:
Map<String, dynamic> dateJson = snapshot.data![index] as Map<String, dynamic>;
DateModel dateModel = DateModel.fromMap(dateJson);
date.dateList.removeAt(index);
await DatabaseHelper.instance.remove(dateModel.id);
PS: You should not make the id optional in your DateModel class since this should always be given.

Flutter Error - The method isn't defined for the type 'Future' - flutter sqflite database error

I am making an app in a flutter in which I can select the contacts from phone book and need to save them into the flutter local database sqflite. I have separate class for database named database_services.dart. In my other .dart file i m using
var _data = DatabaseService.instance.database;
then after that i m calling
_data.getcontacts() // Error statement
and
data.insertContacts(model)
but it is giving me error below
The method 'insertContacts' isn't defined for the type 'Future'. ry correcting the name to the name of an existing method, or defining a method named 'insertContacts'.
Both .dart files are attached for reference. What should i do ? what is wrong ?
my database class :
`
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'contact_model.dart';
class DatabaseService{
DatabaseService._();
static final DatabaseService instance = DatabaseService._();
Database? _database;
String dbName = 'contact.db';
ContactModel model = ContactModel();
Future<Database?> get database async {
if(_database!= null){ return _database!;}
else{
_database = await initializeDB(dbName);
return _database!;
}
}
Future<Database> initializeDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath , filePath);
return await openDatabase(path , version: 1 , onCreate: _CreateDB ) ;
}
Future _CreateDB (Database db , int version) async {
//make like johannes mike at end
await db.execute(
'CREATE TABLE contacts (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT, number TEXT)',
);
}
insertContacts(ContactModel modelObj) async {
// Get a reference to the database.
final db = await instance.database;
//
await db?.insert(
dbName,
modelObj.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<List<ContactModel>?> getcontacts() async {
// Get a reference to the database.
final db = await instance.database;
var response = await db?.query("contacts");
List<ContactModel>? list = response?.map((c) => ContactModel.fromMap(c)).toList();
return list;
/*
return List.generate(maps?.length as int , (i) {
return ContactModel(
id: maps![i]['id'] != null ? toString() : ' ',
displayName: maps[i]['name'] != null ? toString() : ' ',
phoneNumber: maps[i]['number'] != null ? toString() : ' ',
);
});
*/
}
}
`
my other class:
import 'package:firebase_contacts_test/contact_model.dart';
import 'package:firebase_contacts_test/database_services.dart';
import 'package:flutter/material.dart';
import 'package:fluttercontactpicker/fluttercontactpicker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contact_model.dart';
import 'package:sqflite/sqflite.dart';
class Plugin1 extends StatefulWidget {
const Plugin1({Key? key}) : super(key: key);
#override
State<Plugin1> createState() => _Plugin1State();
}
class _Plugin1State extends State<Plugin1> {
var _data = DatabaseService.instance.database;
ContactModel model = ContactModel();
List<ContactModel> _list = [];
PhoneContact? _contact;
String? _phoneContact;
String? _name;
String? _id;
final Permission _permission = Permission.contacts;
PermissionStatus _permissionStatus = PermissionStatus.denied;
Future<PermissionStatus> _getContactPermission() async {
_permissionStatus = await _permission.status;
if (_permissionStatus != PermissionStatus.granted) {
_permissionStatus = await _permission.request();
return _permissionStatus;
} else {
return _permissionStatus;
}
}
Future<void> printDB() async {
print('printintgdsfssfdgsdfg DB');
if(_data != null) {
print( await _data.getcontacts());
}
else{
print('no contacts slected');
}
}
pickContact() async {
PermissionStatus permissionStatus = await _getContactPermission();
if (permissionStatus == PermissionStatus.granted) {
final PhoneContact contact =
await FlutterContactPicker.pickPhoneContact();
print("my_contact");
print(contact);
_phoneContact = contact.phoneNumber?.number;
_name = contact.fullName;
_id = '1';
//set into model
model = ContactModel( id : _id , displayName: _name, phoneNumber: _phoneContact);
_data.insertContacts(model);
_list.add(model);
setState(() {
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
RaisedButton(
onPressed: () {
printDB();
},
child: Text('show Db contacts'),
),
RaisedButton(
onPressed: () {
pickContact();
},
child: Text('select contacts'),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: _list.length,
itemBuilder: (context, position) {
return ListTile(
leading: Icon(Icons.contacts),
title: Text(
_list[position].displayName.toString()
),
trailing: Icon(Icons.delete));
},
),
)
// Text(_phoneContact ?? "contact not selected" ),
// Text(_name ?? "name not selected" ),]
],
));
}
}
my contact model class
import 'package:flutter/cupertino.dart';
class ContactModel {
String? id = 'id';
String? displayName = 'name';
String? phoneNumber = 'number';
ContactModel({ this.id, this.displayName, this.phoneNumber});
//setters
set contactName(String? dispName) {
displayName = dispName;
}
set contactNumber(String? num)
{
phoneNumber = num;
}
//getters
String? get contactName{ return displayName;}
String? get contactNumber{ return phoneNumber;}
// Convert a Dog into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, dynamic> toMap() {
return {
'id': id,
'name': displayName,
'number': phoneNumber,
};
}
factory ContactModel.fromMap(Map<String, dynamic> json) => new ContactModel(
id: json["id"],
displayName: json["name"],
phoneNumber: json["number"],
);
// Implement toString to make it easier to see information about
// each dog when using the print statement.
#override
String toString() {
return 'Dog{id: $id, name: $displayName, age: $phoneNumber}';
}
}//class ends
It should be the following:
await (await _data).getcontacts();
...
await (await _data).insertContacts(model);
This is because _data is an async property and needs an await to get the value out of Future. Also, getcontacts/insertContacts is async and needs another await.
Maybe it'd be nice to get the DB out of _data in another variable like:
final db = await _data;
...
await db.getcontacts();
...
await db.insertContacts(model);

Flutter getting error while inserting values in sqllite

I am trying to insert my data in sqllite
Here is my code
class Cart {
int id;
String title;
String image;
String price;
String color;
String sizeselect;
Cart({
this.id,
this.title,
this.image,
this.price,
this.color,
this.sizeselect,
});
factory Cart.fromJson(Map<String, dynamic> data) => new Cart(
id: data["id"],
title: data["title"],
image: data["image"],
price: data["price"],
color: data["color"],
sizeselect: data["sizeselect"],
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"image": image,
"price": price,
"color": color,
"sizeselect": sizeselect,
};
}
class DatabaseHelper {
static final _databaseName = "MyDatabase.db";
static final _databaseVersion = 1;
static final table = 'my_table';
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// only have a single app-wide reference to the database
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
// lazily instantiate the db the first time it is accessed
_database = await _initDatabase();
return _database;
}
// this opens the database (and creates it if it doesn't exist)
_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 ("
"id INTEGER PRIMARY KEY,"
"title TEXT,"
"image TEXT,"
"color TEXT,"
"price TEXT,"
"sizeselect TEXT"
")");
}
Future<int> insert(cart) async {
print(cart.id);
Database db = await instance.database;
return await db.insert(table, cart);
}
}
I am trying to pass like this
onPressed: () async {
var cart = Cart();
cart.id = widget.product.id;
cart.title = widget.product.title;
cart.image = widget.product.image;
cart.price = widget.product.normalPrice;
cart.color = selectedColor;
cart.sizeselect = selectedSize;
print(cart);
final dbHelper = DatabaseHelper.instance;
final id = await dbHelper.insert(cart);
// Model.createCustomer(map);
}
Its showing this error while passing data type 'Cart' is not a subtype of type 'Map<String, dynamic>'
Can any one please tell i need to convert it to something or what ? I think i need to change the json to String or something ? i just need to insert data in database but on this error i am stuck :/
Edit the line
return await db.insert(table, cart);
With
return await db.insert(table, cart.toJson());
You need to import below third parties
import 'package:path_provider/path_provider.dart';
// path_provider: ^1.6.0
import 'package:sqflite/sqflite.dart';
// sqflite: ^1.3.0
This is DatabaseHelper Class
const String databaseName = "cart.db";
const int databaseVersion = 1;
// ------ CART Table Columns ---------- //
mixin CartTable {
static final String colTitle = "title";
static final String colImage = "image";
static final String colPrice = "price";
static final String colColor = "color";
static final String colSizeSelect = "sizeselect";
}
class DatabaseHelper {
static Database database;
//singleton instance
static DatabaseHelper sharedInstance = new DatabaseHelper._internal();
factory DatabaseHelper() {
return sharedInstance;
}
DatabaseHelper._internal();
Future<Database> get instance async {
if (database != null) {
return database;
}
database = await initDatabase();
return database;
}
initDatabase() async {
io.Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, databaseName);
var db = await openDatabase(path,
version: databaseVersion, onCreate: _onCreateTables);
return db;
}
_onCreateTables(Database db, int version) async {
await createCartTable(db);
}
Future createCartTable(Database db) async {
await db.execute(
"CREATE TABLE ${CartTable.tbCartDetails} ( ${CartTable.colID} INTEGER PRIMARY KEY AUTOINCREMENT, ${CartTable.colTitle} TEXT NOT NULL,"
" ${CartTable.colImage} TEXT NOT NULL, ${CartTable.colPrice} TEXT NOT NULL, ${CartTable.colColor} TEXT NOT NULL,"
" ${CartTable.colSizeSelect} TEXT NOT NULL )");
}
/// Insert Record
Future<dynamic> insertRecord(dynamic data, String tableName) async {
var dbClient = await instance;
return await dbClient.insert(tableName, data.toJson(),
conflictAlgorithm: ConflictAlgorithm.replace);
}
/// Get records
Future<List<dynamic>> getRecords(String table,
{List<String> columns,
String where,
List<dynamic> args,
String groupBy,
String orderBy,
int limit,
int offset}) async {
var dbClient = await instance;
return await dbClient.query(table,
columns: columns,
where: where,
whereArgs: args,
groupBy: groupBy,
orderBy: orderBy,
limit: limit,
offset: offset);
}
/// Update records
Future<dynamic> updateRecord(
{#required String table,
#required List<String> whereColumns,
#required List<dynamic> valuesCondition,
#required Map updateData}) async {
var dbClient = await instance;
String where = '';
whereColumns.forEach((column) => where += " $column=? and");
where = where.substring(0, where.length - 3);
debugPrint(
"Update => $table -> where :$where values:$valuesCondition Data:$updateData");
return await dbClient.update(table, updateData,
where: where, whereArgs: valuesCondition);
}
/// Delete records
Future<dynamic> deleteRecord(
{#required String table,
List<String> whereColumns,
List<dynamic> valuesCondition}) async {
var dbClient = await instance;
String where = '';
whereColumns.forEach((column) => where += " $column=? and");
where = where.substring(0, where.length - 3);
return await dbClient.delete(table,
where: where, whereArgs: valuesCondition);
}
Future close() async {
var dbClient = await instance;
dbClient.close();
}
}
Now, If you want to insert Data into cart_details table
var cart = Cart();
cart.id = widget.product.id;
cart.title = widget.product.title;
cart.image = widget.product.image;
cart.price = widget.product.normalPrice;
cart.color = selectedColor;
cart.sizeselect = selectedSize;
// This needs only once in main.dart
await DatabaseHelper.sharedInstance.initDatabase();
await DatabaseHelper.sharedInstance.insertRecord(cart,CartTable.tbCartDetails);

How to read and write in sqflite database in flutter

Good day everyone,
I am developing an App usaing Flutter.
To save some data localy I am using the SQFlite plugin.
I have a database helper class.
I am using Provider to call my database methods.
When I call the method to write an account in the database I receive an autoincremented ID as response the the sucess of the insertion of the account.
The problem is when I call the method to read these accounts from the database I receiceive nothing. The response Map is null like I have nothing in the database.
If when I insert an account to my database I receive an ID as response, why when I try to read these account I receive nothing.
Please help, me. I am going insane with this code.
class DBProvider {
static const String TABLE_ACCOUNTS = 'Accounts';
static const String COLUMN_ID = 'accountID';
static const String COLUMN_LOCAL_ID = 'id';
static const String COLUMN_CUSTOMER_PICTURE = 'customerPictureBase64';
static const String COLUMN_DOC_FRONT = 'docFrontPictureBase64';
static const String COLUMN_DOC_BACK = 'docBackPictureBase64';
static const String COLUMN_SIGNATURE = 'signatureBase64';
static const String COLUMN_GENDER = 'gender';
static const String COLUMN_FIRST_NAME = 'firstName';
static const String COLUMN_LAST_NAME = 'lastName';
static const String COLUMN_DOC_TYPE = 'docType';
DBProvider._();
static final DBProvider db = DBProvider._();
Database _database;
Future<Database> get database async {
if (_database != null) {
return _database;
}
_database = await createDatabase();
return _database;
}
Future<Database> createDatabase() async {
String dbPath = await getDatabasesPath();
return await openDatabase(
join(dbPath, 'paperless.db'),
version: 1,
onCreate: (Database database, int version) async {
await database.execute(
'CREATE TABLE $TABLE_ACCOUNTS ($COLUMN_LOCAL_ID INTEGER PRIMARY KEY, $COLUMN_ID TEXT, '
'$COLUMN_CUSTOMER_PICTURE TEXT, $COLUMN_DOC_FRONT TEXT, '
'$COLUMN_DOC_BACK TEXT, $COLUMN_SIGNATURE TEXT, '
'$COLUMN_GENDER INTEGER, $COLUMN_FIRST_NAME TEXT, '
'$COLUMN_LAST_NAME TEXT, $COLUMN_DOC_TYPE TEXT)',
);
},
);
}
Future<List<LowKYCAccount>> getLocalLowKYCAccount() async {
final db = await database;
var accounts = await db.rawQuery('SELECT * FROM $TABLE_ACCOUNTS');
var accountsList = List<LowKYCAccount>();
accounts.forEach((account) {
LowKYCAccount kycAccount = LowKYCAccount.fromMap(account);
accountsList.add(kycAccount);
});
return accountsList;
}
Future<LowKYCAccount> saveAccountLocaly(LowKYCAccount account) async {
final db = await database;
account.localId = await db.insert(TABLE_ACCOUNTS, account.toMap());
return account;
}
}
I am calling this methods from my UI sing provider
class LowKYCProvider with ChangeNotifier {
LowKYCAccount _selectedAccount;
List<LowKYCAccount> _lowKycAccounts = [];
List<LowKYCAccount> _localLowKycAccounts = [];
LowKYCAccount get selectedAccount {
return _selectedAccount;
}
List<LowKYCAccount> get lowKycAccounts {
return [..._lowKycAccounts];
}
List<LowKYCAccount> get localLowKycAccounts {
return [..._localLowKycAccounts];
}
Future<void> submitNewAccount(LowKYCAccount account) async {}
Future<void> fetchLowKycAccounts() async {
if (_lowKycAccounts.isEmpty) {
notifyListeners();
}
}
Future<void> fetchLocalLowKycAccounts() async {
print('vamos fetchar os locais');
await DBProvider.db.getLocalLowKYCAccount().then((accounts) {
_localLowKycAccounts = accounts;
//notifyListeners();
});
print('Já terminamos');
}
Future<void> saveAccountLocaly(LowKYCAccount account) async {
await DBProvider.db
.saveAccountLocaly(account)
.then((account) => _localLowKycAccounts.add(account));
notifyListeners();
}
Future<void> updateLowKycAccount(LowKYCAccount account) async {}
Future<void> setSelectedAccount(int index) async {
_selectedAccount = _lowKycAccounts[index];
notifyListeners();
}
}
this is the model class
class LowKYCAccount {
String id;
int localId;
String customerPictureBase64;
String docFrontPictureBase64;
String docBackPictureBase64;
int gender;
String firstName;
String lastName;
String docType;
File signatureFile;
String signatureUrl;
LowKYCAccount({
this.id,
this.localId,
this.customerPictureBase64,
this.docFrontPictureBase64,
this.docBackPictureBase64,
this.gender,
this.firstName,
this.lastName,
this.docType,
this.signatureUrl,
this.signatureFile,
});
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
DBProvider.COLUMN_ID: id,
DBProvider.COLUMN_CUSTOMER_PICTURE: customerPictureBase64,
DBProvider.COLUMN_DOC_FRONT: docFrontPictureBase64,
DBProvider.COLUMN_DOC_BACK: docBackPictureBase64,
DBProvider.COLUMN_GENDER: gender,
DBProvider.COLUMN_FIRST_NAME: firstName,
DBProvider.COLUMN_LAST_NAME: lastName,
DBProvider.COLUMN_DOC_TYPE: docType,
};
if (localId != null) {
map[DBProvider.COLUMN_LOCAL_ID] = localId;
}
return map;
}
LowKYCAccount.fromMap(Map<String, dynamic> account) {
id = account[DBProvider.COLUMN_ID];
localId = account[DBProvider.COLUMN_LOCAL_ID];
customerPictureBase64 = account[DBProvider.COLUMN_CUSTOMER_PICTURE];
docFrontPictureBase64 = account[DBProvider.COLUMN_DOC_FRONT];
docBackPictureBase64 = account[DBProvider.COLUMN_DOC_BACK];
gender = account[DBProvider.COLUMN_GENDER];
firstName = account[DBProvider.COLUMN_FIRST_NAME];
lastName = account[DBProvider.COLUMN_LAST_NAME];
docType = account[DBProvider.COLUMN_DOC_TYPE];
}
}
No experience with this type of plugin or this database, but you should probably use transactions! Otherwise your data will probably not be committed:
await database.transaction((txn) async {
var batch = txn.batch();
// ... insert your data here!
// commit but the actual commit will happen when the transaction is committed
// however the data is available in this transaction
await batch.commit();
// ...
});
and the insert example:
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
print('inserted1: $id1');
int id2 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
['another name', 12345678, 3.1416]);
print('inserted2: $id2');
});
See https://pub.dev/packages/sqflite for more info on transactions