Flutter安卓端读取assets中SQLite数据库文件失败求助
安卓端SQLite数据库加载失败的解决办法
为啥会加载失败?
- FFI在安卓的限制:你用的
databaseFactoryFfi依赖的sqlite3_ffi在安卓上存在路径访问限制,而且assets目录是只读的,FFI无法直接读取该路径下的数据库文件。 - Assets数据库无法直接使用:Flutter将assets文件打包在APK内,该路径下的文件仅可读不可写,而SQLite需要可读写的文件才能正常运行,因此必须先把数据库复制到应用的私有存储目录。
一步步修复
1. 添加必要依赖
在pubspec.yaml中引入以下包,sqlite3_flutter_libs会处理安卓平台的sqlite库适配,path_provider用于获取应用的可读写存储路径:
dependencies: sqlite3_flutter_libs: ^0.5.18 path_provider: ^2.1.1 sqlite3: ^2.4.0
2. 实现数据库复制逻辑
先将assets中的.db文件复制到应用的私有可读写目录,再打开复制后的文件:
import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqlite3/sqlite3.dart'; Future<Database> _initDB(String dbName) async { // 获取应用专属的文档目录(仅当前APP可访问) Directory documentsDir = await getApplicationDocumentsDirectory(); String dbPath = '${documentsDir.path}/$dbName.db'; // 检查数据库是否已复制,未复制则从assets拷贝 if (!await File(dbPath).exists()) { // 读取assets中的数据库文件 ByteData data = await rootBundle.load('assets/你的数据库文件名.db'); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); // 将文件写入可读写路径 await File(dbPath).writeAsBytes(bytes); } // 打开复制完成的数据库 return sqlite3.open(dbPath); }
3. 调整load_names函数
修正数据库初始化与关闭逻辑,优化数据处理流程:
load_names() async { Database database = await _initDB("Questions"); // 执行查询,直接写SQL或用select方法均可 List<Map<String, dynamic>> queryResult = database.select('SELECT name FROM tbl_questions'); database.dispose(); // sqlite3用dispose关闭数据库,而非close // 清空列表避免重复添加数据 tagsList.clear(); for (var row in queryResult) { String name = row['name'] as String; tagsList.add(name); } tagsList.shuffle(); // 一次打乱足够,无需重复操作 }
4. 检查基础配置
- 确保
pubspec.yaml中正确声明assets路径,与实际文件位置一致:
flutter: assets: - assets/你的数据库文件名.db
- 无需手动配置安卓NDK,
sqlite3_flutter_libs已内置不同架构的预编译sqlite库。
关键注意点
- 禁止直接打开assets中的数据库文件,必须复制到可读写路径后再操作
- 安卓平台使用sqlite3库时,关闭数据库调用
dispose()而非close() - 每次加载数据前清空
tagsList,防止重复添加数据
内容的提问来源于stack exchange,提问作者Miumen
相关产品推荐
相关产品推荐

