Flutter使用sqflite实现购物车添加商品时触发Stack Overflow错误
问题定位
栈溢出错误完全由DBHelper类的数据库getter无限递归导致,出错代码片段如下:
Future<Database?> get db async { if (_db != null) { return db; // 错误点1:返回getter自身而非已初始化的_db实例,触发无限自调用 } _db = await initDatabase(); // 错误点2:初始化完成后没有return _db,后续调用永远拿不到已初始化的数据库实例 }
当insert方法执行var dbClient = await db;时:
- 首次调用时
_db为null,进入初始化流程,初始化完成后因为没有return语句,方法返回null - 后续再次调用db getter时,判断
_db != null成立,执行return db,也就是重新调用这个getter本身,无限递归循环会快速占满调用栈,直接抛出Stack Overflow错误。
修复方法
修正DBHelper中db getter的逻辑,消除递归、补全返回值:
class DBHelper { static Database? _db; Future<Database?> get db async { if (_db != null) { // 返回已初始化的私有数据库实例,不要返回getter自身 return _db; } _db = await initDatabase(); // 初始化完成后返回实例 return _db; } // 其余initDatabase、_oncreate、insert、getCartList方法保持原有逻辑即可 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(); } }
可选优化(非报错必需修复)
CartProvider类里存在重复触发通知的问题:_setPrefItems方法内部已经调用了notifyListeners(),但addCounter、removeCounter、addTotalPrice、removeTotalPrice方法在调用_setPrefItems之后又手动调用了一次notifyListeners(),会导致页面无意义的多次刷新,可以删掉这些方法里多余的notifyListeners()调用。
内容的提问来源于stack exchange,提问作者Rashid Ali
相关产品推荐
相关产品推荐

