Stack Overflow error when adding item to cart using sqflite - flutter

i am trying to add product to cart using local database but its giving error stack overflow
here is my cart provider class
class CartProvider with ChangeNotifier {
DBHelper db = DBHelper();
int _counter = 0;
int get counter => _counter;
double _totalPrice = 0.0;
double get totalPrice => _totalPrice;
late Future<List<Cart>> _cart;
Future<List<Cart>> get cart => _cart;
Future<List<Cart>> getData() async {
_cart = db.getCartList();
return _cart;
}
void _setPrefItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('cart_item', _counter);
prefs.setDouble('total_price', _totalPrice);
notifyListeners();
}
void _getPrefsItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_counter = prefs.getInt('cart_item') ?? 0;
_totalPrice = prefs.getDouble('total_price') ?? 0.0;
notifyListeners();
}
void addCounter (){
_counter++;
_setPrefItems();
notifyListeners();
}
void removeCounter (){
_counter--;
_setPrefItems();
notifyListeners();
}
int getCounter(){
_getPrefsItems();
_counter++;
return _counter;
}
void addTotalPrice (double productPrice){
_totalPrice = _totalPrice + productPrice;
_setPrefItems();
notifyListeners();
}
void removeTotalPrice (double productPrice){
_totalPrice = _totalPrice - productPrice;
_setPrefItems();
notifyListeners();
}
double getTotalPrice(){
_getPrefsItems();
return _totalPrice ;
}
}
here is how i am adding it to cart on button click i am getting product from product model class
InkWell(
onTap: () {
dbHelper.insert(
Cart(
id: widget.products.id,
productId: widget.products.id.toString(),
initialPrice: widget.products.price.round(),
productPrice: widget.products.price.round(),
image: widget.products.image,
productName: widget.products.title,
cartDescription: widget.products.description,
quantity: 1,
)
).then((value) {
cart.addTotalPrice(widget.products.price);
cart.addCounter();
print('add to cart');
}).onError((error, stackTrace) {
print(error.toString());
print('error');
});
my database class where i am creating local database where i insert and create database table
class DBHelper {
static Database? _db;
Future<Database?> get db async {
if (_db != null) {
return db;
}
_db = await initDatabase();
}
initDatabase() async {
io.Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, 'cart.db');
var db = await openDatabase(path, version: 1, onCreate: _oncreate);
return db;
}
_oncreate(Database db, int version) async {
await db.execute(
'CREATE TABLE cart (id INTEGER PRIMARY KEY, productId VARCHAR UNIQUE, productName TEXT, initialPrice INTEGER, productPrice INTEGER, quantity INTEGER, cartDescription TEXT, image TEXT)');
}
Future<Cart> insert(Cart cart) async {
var dbClient = await db;
await dbClient!.insert('cart', cart.toMap());
return cart;
}
Future<List<Cart>> getCartList() async {
var dbClient = await db;
final List<Map<String, Object?>> queryResult =
await dbClient!.query('cart');
return queryResult.map((e) => Cart.fromMap(e)).toList();
}
}
kindly help me out when i am adding it to cart its simply print
I/flutter ( 4595): Stack Overflow
on stack trace error
I/flutter ( 6159): #0 DBHelper.insert (package:heem/database/bd_helper.dart:34:19)
I/flutter ( 6159): <asynchronous suspension>
I/flutter ( 6159): #1 FutureExtensions.onError.<anonymous closure> (dart:async/future.dart:1013:15)
I/flutter ( 6159): <asynchronous suspension>

I think the problem is in this getter:
Future<Database?> get db async {
if (_db != null) {
return db;
}
_db = await initDatabase();
}
In return db; you have infinite recursion.
Generally speaking, getters that perform async work are a code smell. Also, what if somebody calls this getter multiple times in parallel?
In my opinion, you should either:
Expose initDatabase method. In every other method require that database is already initialized. This way, you're delegating the responsibility of ensuring initialization before any other operation is performed to the caller of this service (probably your business logic layer). Briefly documenting this assumptions would also be a good idea.
Create a private _ensureInitialized() method which will encapsulate all the logic necessary to ensure correctness:
Completer<Database>? _initCompleter;
Database? _database;
Future<Database> _ensureInitialized() async {
if(_database != null) return _database;
if(_initCompleter != null) return await _initCompleter!.future;
_initCompleter = Completer<Database>();
final database = await _initDatabase();
_database = database;
_initCompleter.complete(database);
return database;
}
Future<void> insert(...) async {
final database = await _ensureInitialized();
...
}

Related

Unhandled Exception: Invalid argument: is a regular instance: Instance of 'LocationDto'

currently I am us this plugin to get the background location of a user, works great with ios but fails on android after recent updates and the plugin progress stalled, I am now faced with the issue below
so, in my main class i have this
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
// onLineStatus = UserSimplePreferences.getUsername() ?? ''
onLineStatus = UserSimplePrefences.getButtonStatus() ?? false;
displayToastMessage(onLineStatus.toString(), context);
osmController = MapController(
initMapWithUserPosition: true,
//initPosition: initPosition,
);
osmController.addObserver(this);
scaffoldKey = GlobalKey<ScaffoldState>();
if (IsolateNameServer.lookupPortByName(
LocationServiceRepository.isolateName) !=
null) {
IsolateNameServer.removePortNameMapping(
LocationServiceRepository.isolateName);
}
IsolateNameServer.registerPortWithName(
port.sendPort, LocationServiceRepository.isolateName);
port.listen(
(dynamic data) async {
if (data != null) await updateUI(data);
},
);
initPlatformState();
}
Future<void> updateUI(LocationDto data) async {
await _updateNotificationText(data);
}
Future<void> _updateNotificationText(LocationDto data) async {
await BackgroundLocator.updateNotificationText(
title: "Your location is updated",
msg: "${DateTime.now()}",
bigMsg: "${data.latitude}, ${data.longitude}");
}
Future<void> initPlatformState() async {
print('Initializing...');
await BackgroundLocator.initialize();
await BackgroundLocator.isServiceRunning();
}
Future<void> _startLocator() async {
Map<String, dynamic> data = {'countInit': 1};
return await BackgroundLocator.registerLocationUpdate(
LocationCallbackHandler.callback,
initCallback: LocationCallbackHandler.initCallback,
initDataCallback: data,
disposeCallback: LocationCallbackHandler.disposeCallback,
iosSettings: IOSSettings(
accuracy: LocationAccuracy.NAVIGATION,
distanceFilter: 0,
stopWithTerminate: true),
autoStop: false,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5,
distanceFilter: 0,
client: LocationClient.google,
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Start Location Tracking',
notificationMsg: 'Track location in background',
notificationBigMsg:
'Background location is on to keep the app up-tp-date with your location. This is required for main features to work properly when the app is not running.',
notificationIconColor: Colors.grey,
notificationTapCallback:
LocationCallbackHandler.notificationCallback)));
}
This is the LocationRepositoryClass
class LocationServiceRepository {
static LocationServiceRepository _instance = LocationServiceRepository._();
LocationServiceRepository._();
factory LocationServiceRepository() {
return _instance;
}
static const String isolateName = 'LocatorIsolate';
int _count = -1;
Future<void> init(Map<dynamic, dynamic> params) async {
//TODO change logs
print("***********Init callback handler");
if (params.containsKey('countInit')) {
dynamic tmpCount = params['countInit'];
if (tmpCount is double) {
_count = tmpCount.toInt();
} else if (tmpCount is String) {
_count = int.parse(tmpCount);
} else if (tmpCount is int) {
_count = tmpCount;
} else {
_count = -2;
}
} else {
_count = 0;
}
print("$_count");
await setLogLabel("start");
final SendPort? send = IsolateNameServer.lookupPortByName(isolateName);
send?.send(null);
}
Future<void> dispose() async {
print("***********Dispose callback handler");
print("$_count");
await setLogLabel("end");
final SendPort? send = IsolateNameServer.lookupPortByName(isolateName);
send?.send(null);
}
#pragma('vm:entry-point')
Future<void> callback(LocationDto locationDto) async {
print('$_count location in dart: ${locationDto.toString()}');
await setLogPosition(_count, locationDto);
final SendPort? send = IsolateNameServer.lookupPortByName(isolateName);
send?.send(locationDto);//error here
_count++;
}
static Future<void> setLogLabel(String label) async {
final date = DateTime.now();
// await FileManager.writeToLogFile(
// '------------\n$label: ${formatDateLog(date)}\n------------\n');
}
static Future<void> setLogPosition(int count, LocationDto data) async {
final date = DateTime.now();
// await FileManager.writeToLogFile(
// '$count : ${formatDateLog(date)} --> ${formatLog(data)} --- isMocked: ${data.isMocked}\n');
}
static double dp(double val, int places) {
num mod = pow(10.0, places);
return ((val * mod).round().toDouble() / mod);
}
static String formatDateLog(DateTime date) {
return date.hour.toString() +
":" +
date.minute.toString() +
":" +
date.second.toString();
}
static String formatLog(LocationDto locationDto) {
return dp(locationDto.latitude, 4).toString() +
" " +
dp(locationDto.longitude, 4).toString();
}
}
and this is the locationCallbackHandler class
class LocationCallbackHandler {
static Future<void> initCallback(Map<dynamic, dynamic> params) async {
LocationServiceRepository myLocationCallbackRepository =
LocationServiceRepository();
await myLocationCallbackRepository.init(params);
}
static Future<void> disposeCallback() async {
LocationServiceRepository myLocationCallbackRepository =
LocationServiceRepository();
await myLocationCallbackRepository.dispose();
}
#pragma('vm:entry-point')
static void callback(LocationDto locationDto) async {
LocationServiceRepository myLocationCallbackRepository =
LocationServiceRepository();
await myLocationCallbackRepository.callback(locationDto);
}
static Future<void> notificationCallback() async {
print('***notificationCallback');
}
}
Everthing was working fine until this update with flutter and kotlin, Now i have the error
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument: is a regular instance: Instance of 'LocationDto'
E/flutter (26006): #0 _SendPort._sendInternal (dart:isolate-patch/isolate_patch.dart:249:43)
E/flutter (26006): #1 _SendPort.send (dart:isolate-patch/isolate_patch.dart:230:5)
E/flutter (26006): #2 LocationServiceRepository.callback
package:drivers_app/tabPages/location_service_reposirtory.dart:59
The error points to this code
#pragma('vm:entry-point')
Future<void> callback(LocationDto locationDto) async {
print('$_count location in dart: ${locationDto.toString()}');
await setLogPosition(_count, locationDto);
final SendPort? send = IsolateNameServer.lookupPortByName(isolateName);
send?.send(locationDto); //error here
_count++;
}
There is no reply from the plugin developer, Any help would be appreciated.
https://github.com/Yukams/background_locator_fixed/pull/53
There were some errors after updating flutter to version 3, If you run into this error then please visit the above website for the fix.

Flutter - Widget that no longer appears in the widget tree or this error might indicate a memory leak Warning

I have 3 page I check transitions with bottomNavigationBar first page is Soclose in this page im gettting information from the database and print it on the screen.
I'm getting information from the database smoothly but when i switch screens my console gives warning messages. An error appears in the console, but the application is working properly. When changing screens and returning to the old page(Soclose page), an error page appears and disappears within milliseconds.
I cant find similar questions and i tried to make suggestions in the warnings but either I couldn't do it or the solutions don't work.
Related soclose dart file:
class _Closesevents extends State<Soclose> {
List<Event> eventList;
int eventListLen;
#override
void initState() {
try{
final Future<Database> dbFuture = DbHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Event>> eventListFuture = DbHelper().getEventList();
eventListFuture.then((eventList) {
setState(() {
this.eventList = eventList;
this.eventListLen = eventList.length;
});
});
});}
catch (e,s)
{
print("[ERROR] $e");
print("[ERROR TREE]\n$s");
}
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container(
child: new ListView.builder(
itemCount: eventListLen,
itemBuilder: (BuildContext context, int index) =>
buildTripCard(context, index)),
);
}
Widget buildTripCard(BuildContext context, int index)
...
Databasehelper file
import ...
class DbHelper {
static DbHelper _databaseHelper; // Singleton DatabaseHelper
static Database _database;
static final String _tablename = EventConstants.TABLE_NAME;
static final String _columnId = EventConstants.COLUMN_ID;
static final String _columnTitle = EventConstants.COLUMN_TITLE;
static final String _columnDate = EventConstants.COLUMN_DATE;
static final String _columnStartTime = EventConstants.COLUMN_STARTTIME;
static final String _columnFinishTime = EventConstants.COLUMUN_FINISHTIME;
static final String _columnDesc = EventConstants.COLUMN_DESCRIPTION;
static final String _columnIsActive = EventConstants.COLUMN_ISACTIVE;
DbHelper._createInstance(); // Named constructor to create instance of DatabaseHelper
factory DbHelper() {
if (_databaseHelper == null) {
_databaseHelper = DbHelper._createInstance(); // This is executed only once, singleton object
}
return _databaseHelper;
}
Future<Database> get database async {
if (_database == null) {
_database = await initializeDatabase();
}
return _database;
}
static Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'takvimapp.db';
// Open/create the database at a given path
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}
static void _createDb(Database db, int newVersion) async {
await db.execute('CREATE TABLE $_tablename ( $_columnId INTEGER PRIMARY KEY NOT NULL,$_columnTitle TEXT ,$_columnDate TEXT,$_columnStartTime TEXT,$_columnFinishTime TEXT,$_columnDesc TEXT,$_columnIsActive INTEGER);');
}
// Get all events --map
Future<List<Map<String, dynamic>>> getEventMapList() async {
Database db = await this.database;
var result = await db.query(_tablename, orderBy: '$_columnTitle ASC');
return result;
}
// Insert Operation: Insert a Event object to database
Future<int> insertEvent(Event event) async {
Database db = await this.database;
var result = await db.insert(_tablename, event.toMap());
return result;
}
// Update Operation: Update a Event object and save it to database
Future<int> updateEvent(Event event) async {
var db = await this.database;
var result = await db.update(_tablename, event.toMap(), where: '$_columnId = ?', whereArgs: [event.id]);
return result;
}
// Delete Operation: Delete a Event object from database
Future<int> deleteEvent(int id) async {
var db = await this.database;
int result = await db.rawDelete('DELETE FROM $_tablename WHERE $_columnId = $id');
return result;
}
// Get number of Event objects in database
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from $_tablename');
int result = Sqflite.firstIntValue(x);
return result;
}
// Convert map to list
Future<List<Event>> getEventList() async {
var eventMapList = await getEventMapList(); // Get 'Map List' from database
int count = eventMapList.length; // Count the number of map entries in db table
List<Event> eventList = List<Event>();
// For loop to create a 'Event List' from a 'Event List'
for (int i = 0; i < count; i++) {
eventList.add(Event.fromMap(eventMapList[i]));
}
return eventList;
}
static Future closeDb() => _database.close();
}
The error warning is constantly written to the console in an infinite loop.
To get rid of the warning, I need to close the app and restart the emulator.
Warning message:
E/flutter (30455): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: setState() >called after dispose(): _CountDownItemState#2bbc3(lifecycle state: defunct, not mounted)
E/flutter (30455): This error happens if you call setState() on a State object for a widget that no >longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its >build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (30455): The preferred solution is to cancel the timer or stop listening to the animation >in the dispose() callback.
Another solution is to check the "mounted" property of this object >before calling setState() to ensure the object is still in the tree.
E/flutter (30455): This error might indicate a memory leak if setState() is being called because >another object is retaining a reference to this State object after it has been removed from the >tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
Solution:
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _db.getEventList(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Text("Loading....."),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].title),
);
});
}
}),
);
}
The issue is with your initState function override. It's good practice to also call the super of initState, super.initState, before all other logic. Your Futures may be completing too quickly, and calling setState before the state is even initialized. Simply move super.initState(); as the first statement in the override. Ex.
#override
void initState() {
super.initState();//Always call this first
try{
final Future<Database> dbFuture = DbHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Event>> eventListFuture = DbHelper().getEventList();
eventListFuture.then((eventList) {
setState(() {
this.eventList = eventList;
this.eventListLen = eventList.length;
});
});
});}
catch (e,s)
{
print("[ERROR] $e");
print("[ERROR TREE]\n$s");
}
}
Edit: However, this can still lead to errors as setState could still be called before the widget is mounted. This is why the FutureBuilder widget exists. Wrap the widget that needs this Future data in your build method, pass the Future to the future parameter of the FutureBuilder and access the data with the AsyncSnapshot that the builder provides. See more about FutureBuilder.

GetInt was called on null

Am I doing anything wrong with sharedPreferences in flutter.
SharedPreferences prefs;
int score;
int storedScore;
final String uid;
StoredData(this.uid) {
_initialize();
_readValues();
}
_initialize() async {
prefs = await SharedPreferences.getInstance();}
_readValues() {
score = prefs.getInt("score") ?? 0;
storedScore = prefs.getInt("storedScore") ?? 0;}
error:
I/flutter (18698): The method 'getInt' was called on null.
I/flutter (18698): Receiver: null
I/flutter (18698): Tried calling: getInt("score")
The relevant error-causing widget was:
I/flutter (18698): HomeScreen file:///D:/flutter/trivia_iq/trivia_iq/lib/main.dart:24:33
This is not in the main.dart file but I am getting this.
Any help will be appreciated.
This gives null as shared preference object object haven't created till now, and you are using it somewhere.
You have to add Future as you do await for some background work
Future<Void> _initialize() async {
prefs = await SharedPreferences.getInstance();
}
Calling Function Like:
_initialize().then((value) => _readValues());
In "StoredData()" constructor you should use await also when calling "_initialize()" method:
await _initialize();
If not "_readValues()" would be called when sharedPreferences are not yet initialized.
But because use of async on constructors is not permitted, you should change initialize() like this:
_initialize() async {
prefs = await SharedPreferences.getInstance();
score = prefs.getInt("score") ?? 0;
storedScore = prefs.getInt("storedScore") ?? 0;
}
In your widget you can do something like this:
class MyWidget extends StatelessWidget{
#override
Widget build(BuildContext context){
return MaterialApp(
home: FutureBuilder(
future: StoredData._initialize(),
builder: (_,snap){
if (snap.connectionState==ConnectionState.done)
return Text("Settings loaded");
else
return Text("Loading settings...");
}
),);
}
}
class StoredData {
static SharedPreferences _prefs;
static int score;
static int storedScore;
final String uid;
StoredData(this.uid);
static Future _initialize() async {
_prefs = await SharedPreferences.getInstance();
score = _prefs.getInt("score") ?? 0;
storedScore = _prefs.getInt("storedScore") ?? 0;
}
}
StoredData(this.uid) {
_initialize().then((value) => _readValues());
shouldStoreInFirebase();}
Future<void> _initialize() async {
prefs = await SharedPreferences.getInstance();}
_readValues() {
score = prefs.getInt("score") ?? 1;
storedScore = prefs.getInt("storedScore") ?? 0;
}

my list is not displaying when reading async from database

I have a screen that is reading data from a database table (sqllite) but the data is not been display in my listview. it looks like when i read the data the screen already display the gui and my array is not populated with data by the time the listview access the array.
below is my code
import 'package:finsec/model/cardview_list_item.dart';
import 'package:flutter/material.dart';
import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/widget/circle_icon.dart';
import 'package:finsec/data/db_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:finsec/utils/queries.dart';
class CardviewListItemData extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return CardviewListItemDataState();
}
}
class CardviewListItemDataState extends State<CardviewListItemData> {
DBProvider db = new DBProvider();
List<String> amountList;
List<CardviewListItem> listItems = List<CardviewListItem>();
int count = 0;
#override
Widget build(BuildContext context) {
if (amountList == null) {
amountList = List<String>();
updateListView();
listItems = summaryList();
}
return ListView.builder(
itemCount: listItems.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(listItems[index].icon, color: listItems[index].iconColor),
title: Align(
child: new Text(listItems[index].title,style: TextStyle(fontSize: 16)),
alignment: Alignment(-1.4, 0),
),
trailing: new Text(listItems[index].amount, style: TextStyle(fontSize: 16),),
//onTap: () => onTapped(context, listItems[index].title),
);
},
);
}
List<CardviewListItem> summaryList() {
List<CardviewListItem> summaryListItems = List<CardviewListItem>();
CardviewListItem income = new CardviewListItem(
title: totalIncome,
amount: amountList[0],
icon: Icons.attach_money,
iconColor: green
);
summaryListItems.add(income);
return summaryListItems;
}
void updateListView() {
final Future<Database> dbFuture = db.initializeDatabase();
dbFuture.then((database) {
Future<List<String>> incomeListFuture = db.getDataList(test);
incomeListFuture.then((amountList) {
setState(() {
this.amountList = amountList;
this.count = this.amountList.length;
});
});
});
}
}
my database code is
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:finsec/model/transaction_content.dart';
import 'package:finsec/utils/tables.dart';
import 'package:finsec/model/income/income_dao.dart';
import 'package:finsec/model/income/income.dart';
import 'package:finsec/model/list_item.dart';
import 'package:finsec/model/dao.dart';
import 'package:finsec/model/cardview_list_item.dart';
import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/widget/circle_icon.dart';
import 'package:finsec/data/db_provider.dart';
class DBProvider {
static DBProvider db; // Singleton DBProvider
static Database _database; // Singleton Database
DBProvider._createInstance(); // Named constructor to create instance of DBProvider
factory DBProvider() {
if (db == null) {
db = DBProvider._createInstance(); // This is executed only once, singleton object
}
return db;
}
Future<Database> get database async {
if (_database == null) {
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
// Get the directory path for both Android and iOS to store database.
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'finsec.db';
// Open/create the database at a given path
var finsecDatabase = await openDatabase(path, version: 4, onCreate: _createDb, onUpgrade: _onUpgrade);
return finsecDatabase;
}
void _createDb(Database db, int newVersion) async {
// await db.execute('drop table income');
print('CREATE THE TABLE2');
await db.execute(incomeTable);
//await db.execute("CREATE TABLE User(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, dob TEXT)");
}
// UPGRADE DATABASE TABLES
void _onUpgrade(Database db, int oldVersion, int newVersion) async {
if (oldVersion < newVersion) {
await db.execute('drop table income');
await db.execute(incomeTable);
}
}
// Fetch Operation: Get all row objects from database
Future<List<Map<String, dynamic>>> getTransactions(String tableName) async {
Database db = await this.database;
//var result = await db.rawQuery(tableName);
var result = await db.query(tableName);
result.forEach((row) => print(row));
// var res = await db.insert('note', transactionType.toMap());
return result;
}
// Fetch Operation: Get all row objects from database
Future<List<Map<String, dynamic>>> getTransactionsQuery(String query) async {
Database db = await this.database;
var result = await db.rawQuery(query);
return result;
}
// Insert Operation: Insert a transaction object to database
Future<int> insertTransaction(String sqlQuery) async {
Database db = await this.database;
//var dao = new IncomeDao();
var result = await db.rawInsert(sqlQuery); //insert(noteTable, note.toMap());
//var result = await db.insert('noteTable', transaction);
return result;
}
// Update Operation: Update a Note object and save it to database
Future<int> updateTransaction(Map transaction) async {
var db = await this.database;
//var result = await db.rawUpdate(sql);// update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
var result = await db.update('noteTable', transaction);
return result;
}
// Delete Operation: Delete a transaction object from database
Future<int> deleteTransaction(int id) async {
var db = await this.database;
int result = await db.rawDelete('DELETE FROM noteTable WHERE ');
return result;
}
// Get number of Note objects in database
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from noteTable');
int result = Sqflite.firstIntValue(x);
return result;
}
// Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
Future<List<Income>> getIncomeList(String tableName) async {
var incomeMapList = await getTransactions(tableName); // Get 'Map List' from database
int count = incomeMapList.length; // Count the number of map entries in db table
List<Income> incomeList = List<Income>();
// For loop to create a 'Income List' from a 'Map List'
for (int i = 0; i < count; i++) {
incomeList.add(Income.fromMap(incomeMapList[i]));
}
return incomeList;
}
// Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
Future<List<String>> getDataList(String query) async {
var dataMapList = await getTransactionsQuery(query); // Get 'Map List' from database
int count = dataMapList.length; // Count the number of map entries in db table
List<String> dataList = List<String>();
Map<String, dynamic> queryData;
for (int i = 0; i < count; i++) {
queryData = dataMapList[i];
dataList.add(queryData["amount"]);
}
return dataList;
}
}
i think the problem is in the following portion of the code
if (amountList == null) {
amountList = List<String>();
updateListView();
listItems = summaryList();
}
updateListView() is getting called but it looks like the code continue executing to the next line even if updateListView didnt finish executing. when i called amountList[0] in summaryList(), i get the following error
RangeError (index): Invalid value: Valid value range is empty: 0
I/flutter ( 3640):
I/flutter ( 3640): User-created ancestor of the error-causing widget was:
I/flutter ( 3640): Column file:///C:/Users/rodrigue33/Documents/APP/finsec/lib/widget/cardview_widget.dart:45:22
I/flutter ( 3640):
I/flutter ( 3640): When the exception was thrown, this was the stack:
I/flutter ( 3640): #0 List.[] (dart:core-patch/growable_array.dart:145:60)
I/flutter ( 3640): #1 CardviewListItemDataState.summaryList (package:finsec/data/cardview_list_item.dart:114:27)
I/flutter ( 3640): #2 CardviewListItemDataState.build (package:finsec/data/cardview_list_item.dart:80:19)
I/flutter ( 3640): #3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4040:27)
this is my assumption of what is happening. do anyone agree with me? how can i solve this issue of waiting for database to return data before displaying the data in the listview? thanks in advance
The problem is that you are calling the setState method and updating its "amountList", as setState reloads the page it doesn't quite execute "listItems = summaryList ();".
Perhaps a quick fix would be to create a bool check and leave it false, set to true when setState is executed, and within your builder method do:
if (amountList == null) {
amountList = List<String>();
updateListView();
}
if(check){
listItems = summaryList();
}
NOTE: I suggest using async and await in your methods instead of future.
void updateListView() async{
final Database db = await db.initializeDatabase();
List<String> incomeList = await db.getDataList(test);
setState(() {
this.amountList = amountList;
this.count = this.amountList.length;
this.check = true;
});
}
I hope I helped you!

Execute if database exists flutter

So basically what i want to do is:
When the user turns on the app for the first time,
The SQLite database is created and the data is fetched from the internet.
Until this is done, SetupPage() widget is displayed in scaffolds body or else Home() is displayed.
Now the code i wrote works perfectly for the first time, but when i open it the second time,
The SetupPage() only shows, it never goes back to the Home(). What am i doing wrong here ?
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:path/path.dart';
import 'pages/home.dart';
import 'pages/SetUpPage.dart';
import 'package:sqflite/sqflite.dart';
class App extends StatefulWidget {
createState() {
return AppState();
}
}
class AppState extends State<App> {
final bgColor = const Color(0xFF1abc9c);
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
bool status = false;
Database database;
#override
void initState() {
initializeData();
super.initState();
}
void initializeData() async
{
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');
status = false;
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute(
'CREATE TABLE news (id INTEGER PRIMARY KEY, topic TEXT, img TEXT, newstitle TEXT, news TEXT, newslink TEXT)');
fetchData();
}
);
database.close();
}
#override
Widget build(context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("UnFound News"),
backgroundColor: bgColor,
),
body: status ? Home() : SetUpPage(),
);
}
/*Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);*/
void fetchData() async {
var result = await get("https://api.myjson.com/bins/a0bvu");
var arr = json.decode(result.body)['post'];
for(int i = 0; i < arr.length; i++)
{
//TODO: Implement addition to database.
}
setState(() {
status = true;
});
}
}
You probably want to put the fetchData in a onOpen parameter instead of the onCreate parameter like this:
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute(
'CREATE TABLE news (id INTEGER PRIMARY KEY, topic TEXT, img TEXT, newstitle TEXT, news TEXT, newslink TEXT)');
await fetchData();
}, onOpen: (Database db) async {
setState(() {
status = true;
});
});
static Database _db;
Future<Database> get db async {
if(_db != null)
return _db;
_db = await initDb();
return _db;
}
//Creating a database with name test.dn in your directory
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "test.db");
var theDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return theDb;
}
checkDb(){
//do operation
var dbClient = await db;
}