[英]Flutter sqflite - Problem loading database from asset
我正在使用以下代码从资产中复制数据库。 大多数时候,这段代码工作正常。 但是,在我的应用发布到应用商店后,我收到了一些用户的抱怨,称数据库无法加载。 然后我在自己的 iPhone 上尝试,卸载并再次从应用商店下载该应用。 奇怪的是在大约 10 次安装中,有 1 次数据库加载失败。 这是我的数据库助手:
class DatabaseHelper {
static const NEW_DB_VERSION = 6;
static final DatabaseHelper _instance = DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
DatabaseHelper.internal();
Database _db;
Future<Database> get db async {
if (_db != null) {
return _db;
} else {
_db = await initDb();
return _db;
}
}
Future<Database> initDb() async {
final databasesPath = await getDatabasesPath();
final path = join(databasesPath, "dictionary");
var db = await openDatabase(path);
//if database does not exist yet it will return version 0
if (await db.getVersion() < NEW_DB_VERSION) {
db.close();
try {
await Directory(dirname(path)).create(recursive: true);
} catch (_) {}
//copy db from assets to database folder
ByteData data = await rootBundle.load("assets/dictionary");
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(path).writeAsBytes(bytes, flush: true);
//open the newly created db
db = await openDatabase(path);
//set the new version to the copied db so you do not need to do it manually on your bundled database.db
db.setVersion(NEW_DB_VERSION);
}
return db;
}
}
我通过使用在我的主要活动中初始化数据库
DatabaseHelper db = DatabaseHelper();
为什么会出现这个奇怪的问题?
如果 db/initDb 被多次调用(并且它可能发生在您的代码中),可能会发生一些竞争条件,这可能会产生一些不可预测的结果。
我宁愿将您的 initDb 设为私有,并确保它不会被多次调用,例如:
import 'package:sqflite_common/sqlite_api.dart';
import 'package:synchronized/synchronized.dart';
class OpenHelper {
Database _db;
final _dbLock = Lock();
Future<Database> get db async {
if (_db != null) {
return _db;
} else {
// Safe guard _initDb so that it is ran only once
await _dbLock.synchronized(() async {
// Don't call it if _db is defined.
_db ??= await _initDb();
});
return _db;
}
}
}
甚至更简单(但不存储数据库引用,只有未来):
import 'package:sqflite_common/sqlite_api.dart';
class OpenHelper {
Future<Database> _db;
Future<Database> get db {
_db ??= _initDb();
return _db;
}
看看这是否能解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.