我正在使用以下代码从资产复制数据库。大多数时候,此代码都能正常工作。但是,在将我的应用发布到应用商店后,我收到了一些用户的投诉,导致数据库无法加载。然后,我尝试用自己的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();
为什么这个奇怪的问题发生了?
答案 0 :(得分:1)
如果多次调用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;
}
然后查看是否可以解决问题。