Rashid Ali
Rashid Ali

Reputation: 197

Stack Overflow error when adding item to cart using sqflite

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>

Upvotes: 0

Views: 460

Answers (1)

mfkw1
mfkw1

Reputation: 1161

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:

  1. 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.
  2. 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();
  ...
}

Upvotes: 1

Related Questions