You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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提供了全局唯一的实例,这才是正确的获取方式。

解决方案

  1. 替换实例获取方式:将Provider中创建DatabaseHelper实例的代码,从调用私有构造函数改为使用已定义的instance静态变量。
  2. 优化数据库操作:直接使用DatabaseHelper提供的封装方法(如addMedication、updateMedication),避免重复编写数据库操作代码。
  3. 修正类型不匹配问题:原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:25:17