Flutter报错:DatabaseHelper类无_privateConstructor构造方法
解决DatabaseHelper私有构造函数调用报错问题
问题场景
在Provider中调用DatabaseHelper._privateConstructor()创建实例时,收到错误提示:
The class DatabaseHelper doesn't have a constructor named _privateConstructor
但该私有构造方法已在DatabaseHelper类中定义,相关代码如下:
DatabaseHelper代码
import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; import '../models/medication_model.dart'; class DatabaseHelper { static final DatabaseHelper instance = DatabaseHelper._privateConstructor(); static Database? _database; DatabaseHelper._privateConstructor(); Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future<Database> _initDatabase() async { final String path = await getDatabasesPath(); return openDatabase( join(path, 'medications.db'), version: 1, onCreate: _createDatabase, ); } Future<void> _createDatabase(Database db, int version) async { await db.execute(''' CREATE TABLE medications( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, dosage TEXT, frequency TEXT, start_date INTEGER, end_date INTEGER, notes TEXT ) '''); } Future<int> addMedication(Medication medication) async { final db = await database; return db.insert('medications', medication.toMap()); } Future<int> updateMedication(Medication medication) async { final db = await database; return db.update( 'medications', medication.toMap(), where: 'id = ?', whereArgs: [medication.id], ); } Future<int> deleteMedication(int id) async { final db = await database; return db.delete( 'medications', where: 'id = ?', whereArgs: [id], ); } Future<List<Medication>> getMedications() async { final db = await database; final List<Map<String, dynamic>> medicationData = await db.query('medications'); return medicationData.map((data) => Medication.fromMap(data)).toList(); } }
原Provider代码(报错部分)
import 'package:flutter/foundation.dart'; import 'package:medbuddy/models/medication_model.dart'; import 'package:medbuddy/utils/database_helper.dart'; class MedicationProvider extends ChangeNotifier { List<Medication> _medications = []; List<Medication> get medications => _medications; // 此处调用私有构造函数导致报错 DatabaseHelper database = DatabaseHelper._privateConstructor(); void addMedication(Medication medication) async { _medications.add(medication); notifyListeners(); final db = await database.database; await db.insert('medications', medication.toMap()); } void updateMedication(Medication medication) async { final index = _medications.indexWhere((element) => element.id == medication.id); _medications[index] = medication; notifyListeners(); final db = await database.database; await db.update('medications', medication.toMap(), where: 'id = ?', whereArgs: [medication.id]); } Future<void> deleteMedication(String id) async { _medications.removeWhere((element) => element.id == id); notifyListeners(); final db = await database.database; await db.delete('medications', where: 'id = ?', whereArgs: [id]); } Future<void> loadMedications() async { final db = await database.database; final List<Map<String, dynamic>> medicationData = await db.query('medications'); _medications = medicationData.map((data) => Medication.fromMap(data)).toList(); notifyListeners(); } Future<void> init() async { await loadMedications(); } }
报错原因
Dart中,以下划线_开头的成员(包括构造函数)属于库私有成员,只能在定义它的同一个.dart文件内部访问。Provider代码位于另一个文件,因此无法直接调用_privateConstructor()。
而你的DatabaseHelper已经实现了单例模式,通过static final DatabaseHelper instance提供了全局唯一的实例,这才是正确的获取方式。
解决方案
- 替换实例获取方式:将Provider中创建DatabaseHelper实例的代码,从调用私有构造函数改为使用已定义的
instance静态变量。 - 优化数据库操作:直接使用DatabaseHelper提供的封装方法(如
addMedication、updateMedication),避免重复编写数据库操作代码。 - 修正类型不匹配问题:原Provider中
deleteMedication的参数是String id,但数据库中id是INTEGER类型,需改为int id避免类型错误。
修正后的Provider代码
import 'package:flutter/foundation.dart'; import 'package:medbuddy/models/medication_model.dart'; import 'package:medbuddy/utils/database_helper.dart'; class MedicationProvider extends ChangeNotifier { List<Medication> _medications = []; List<Medication> get medications => _medications; // 使用单例实例,避免调用私有构造函数 final DatabaseHelper _databaseHelper = DatabaseHelper.instance; Future<void> addMedication(Medication medication) async { // 先调用数据库方法添加,获取返回的自增id final int newId = await _databaseHelper.addMedication(medication); medication.id = newId; _medications.add(medication); notifyListeners(); } Future<void> updateMedication(Medication medication) async { await _databaseHelper.updateMedication(medication); final index = _medications.indexWhere((element) => element.id == medication.id); if (index != -1) { _medications[index] = medication; notifyListeners(); } } Future<void> deleteMedication(int id) async { await _databaseHelper.deleteMedication(id); _medications.removeWhere((element) => element.id == id); notifyListeners(); } Future<void> loadMedications() async { _medications = await _databaseHelper.getMedications(); notifyListeners(); } Future<void> init() async { await loadMedications(); } }
额外说明
- 单例模式的核心就是通过静态实例控制对象创建,避免多次初始化数据库连接,你的DatabaseHelper已经正确实现了这一点,只需直接使用
instance即可。 - 修正后的代码将数据库操作逻辑完全委托给DatabaseHelper,符合单一职责原则,也减少了代码重复。
内容的提问来源于stack exchange,提问作者Muhammad AsfandYar Amjad
相关产品推荐
相关产品推荐

