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

Flutter中导入现有SQLite数据库并初始化连接失败求助

Flutter新手数据库调用报错问题

我是Flutter新手,已将sms.db放在assets/db目录并在pubspec.yaml配置了资源路径,尝试把数据库复制到应用目录后,在categoriesList.dart调用SmsDataBaseHelper.instance.getAllCategories()时出现错误。


pubspec.yaml配置

assets:
    - assets/db/sms.db

database_helper.dart代码

import 'package:flutter/services.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'dart:io' as io;
import '/models/categories.dart';


class SmsDataBaseHelper {
    static final SmsDataBaseHelper instance = SmsDataBaseHelper._();
    static Database? _db;
    
    SmsDataBaseHelper._();
    
    Future<Database> get db async {
        _db  ??= await _init();
        return _db!;
    }
    
    Future<Database> _init() async {
        io.Directory applicationDirectory = await getApplicationDocumentsDirectory();
        String dbPathSms =  path.join(applicationDirectory.path, "sms.db");
        bool dbExistsSms = await io.File(dbPathSms).exists();
        if (!dbExistsSms) {
          // Copy from asset
          ByteData data = await rootBundle.load(path.join("assets", "db", "sms.db"));
          List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
          // Write and flush the bytes written
          await io.File(dbPathSms).writeAsBytes(bytes, flush: true);
        }
        return await openDatabase(dbPathSms);
    }

    /// get all the words from categories
    Future<List<Categories>> getAllCategories() async {
        if (_db == null) {
          throw "_db is not initiated, initiate using [init(db)] function";
        }
        List<Map>? categories;

        await _db!.transaction((txn) async {
          categories = await txn.query(
            "categories",
            columns: [
              "name",
              "ru",
            ],
          );
        });

        return categories!.map((e) => Categories.fromJson(e as Map<String, dynamic>)).toList();
    }
}

categoriesList.dart代码

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import '../utils/database_helper.dart';
import '../models/categories.dart';


class CategoriesList extends StatefulWidget {
    const CategoriesList({super.key});

    @override
    State<CategoriesList> createState() => _CategoriesListState();
}

class _CategoriesListState extends State<CategoriesList> {
  //late List<Categories> categoriesList;

  @override
  void initState(){
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

        return Scaffold(
            appBar: AppBar(
                title: const Text('SMS Home Page'),
            ),
            body: FutureBuilder<List<Categories>>(
                future: SmsDataBaseHelper.instance.getAllCategories(),
                builder: (BuildContext context, AsyncSnapshot<List<Categories>> snapshot) {
                    switch (snapshot.connectionState) {
                        case ConnectionState.none:
                            return const Text('start widget');
                        case ConnectionState.active:
                        case ConnectionState.waiting:
                            return const Text('Awaiting result from api...');
                        case ConnectionState.done:
                            if (snapshot.hasError)
                                return Text('Error: ${snapshot.error}');
                            return Text('Result: ${snapshot.data}');
                    }
                },
            ),
        );
    }
}

错误信息

调用后抛出错误:_db is not initiated, initiate using [init(db)] function


问题原因及解决办法

问题出在getAllCategories方法直接判断_db == null,但_db是通过异步getterdb初始化的,调用getAllCategories时可能还未完成初始化。

修改getAllCategories方法如下:

Future<List<Categories>> getAllCategories() async {
    // 先确保数据库初始化完成
    final database = await db;
    List<Map> categories = await database.transaction((txn) async {
      return await txn.query(
        "categories",
        columns: [
          "name",
          "ru",
        ],
      );
    });

    return categories.map((e) => Categories.fromJson(e as Map<String, dynamic>)).toList();
}

修改说明:

  1. 用await db替代直接判断_db,确保数据库实例初始化完成后再执行查询
  2. 直接接收事务的返回值,避免原代码中可空变量强制解包的风险

内容的提问来源于stack exchange,提问作者Yaroslav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:50:25