我真的不知道问题出在哪里...有人可以告诉我应该怎么做才能解决数据库锁定吗?
这是我的sqlite代码
class DatabaseHelper {
static DatabaseHelper? _databaseHelper;
static Database? _database;
DatabaseHelper._internal() {
_databaseHelper = this;
}
factory DatabaseHelper() {
_databaseHelper ??= DatabaseHelper._internal();
return _databaseHelper!;
}
Future<Database?> get database async {
_database = await _initializeDB();
return _database;
}
final String _tableAndung = 'job_andung';
final String _tableImran = 'job_imran';
final String _tableAksa = 'job_aksa';
Future<Database> _initializeDB() async {
var db = await openDatabase(
join(
await getDatabasesPath(),
'multimedia_job.db', // Mengganti nama database
),
onCreate: (db, version) async {
// Pembuatan tabel data kak Andung
await db.execute(
'''CREATE TABLE $_tableAndung(
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
fb INTEGER,
yt INTEGER,
shorts INTEGER,
ig INTEGER,
tiktok INTEGER,
total INTEGER,
targetFb INTEGER,
targetYt INTEGER,
targetShorts INTEGER,
targetIg INTEGER,
targetTiktok INTEGER,
targetTotal INTEGER)''',
);
// Pembuatan tabel data kak Imran
await db.execute(
'''CREATE TABLE $_tableImran(
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
fb INTEGER,
yt INTEGER,
shorts INTEGER,
ig INTEGER,
tiktok INTEGER,
total INTEGER,
targetFb INTEGER,
targetYt INTEGER,
targetShorts INTEGER,
targetIg INTEGER,
targetTiktok INTEGER,
targetTotal INTEGER)''',
);
// Pembuatan tabel data kak Aksa
await db.execute(
'''CREATE TABLE $_tableAksa(
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
fb INTEGER,
yt INTEGER,
shorts INTEGER,
ig INTEGER,
tiktok INTEGER,
total INTEGER,
targetFb INTEGER,
targetYt INTEGER,
targetShorts INTEGER,
targetIg INTEGER,
targetTiktok INTEGER,
targetTotal INTEGER)''',
);
},
version: 1,
);
return db;
}
//Mengambil data Kak Andung
Future<List<AndungJobModels>> getListAndung() async {
final db = await database;
List<Map<String, dynamic>> results = [];
await db!.transaction((txn) async {
results = await txn.query(_tableAndung);
});
return results
.map(
(e) => AndungJobModels.fromMap(e),
)
.toList();
}
// Mengambil data Kak Imran
Future<List<ImranJobModels>> getListImran() async {
final db = await database;
List<Map<String, dynamic>> results = [];
await db!.transaction((txn) async {
results = await txn.query(_tableImran);
});
return results
.map(
(e) => ImranJobModels.fromMap(e),
)
.toList();
}
// Mengambil data Kak Aksa
Future<List<AksaJobModels>> getListAksa() async {
final db = await database;
List<Map<String, dynamic>> results = [];
await db!.transaction((txn) async {
results = await txn.query(_tableAksa);
});
return results
.map(
(e) => AksaJobModels.fromMap(e),
)
.toList();
}
//Menambahkan data kak Andung kedalam tabel
Future<void> insertJobAndung(AndungJobModels dataModel) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.insert(
_tableAndung,
dataModel.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
},
);
}
Future<void> insertJobImran(ImranJobModels dataModel) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.insert(
_tableImran,
dataModel.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
},
);
}
Future<void> insertJobAksa(AksaJobModels dataModel) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.insert(
_tableAksa,
dataModel.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
},
);
}
Future<void> removeAndungJob(int id) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.delete(
_tableAndung,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
Future<void> removeImranJob(int id) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.delete(
_tableImran,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
Future<void> removeAksaJob(int id) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.delete(
_tableAksa,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
Future<void> updateAndungJob(
int id, Map<String, dynamic> updatedValues) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.update(
_tableAndung,
updatedValues,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
Future<void> updateImranJob(
int id, Map<String, dynamic> updatedValues) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.update(
_tableImran,
updatedValues,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
Future<void> updateAksaJob(int id, Map<String, dynamic> updatedValues) async {
final db = await database;
await db!.transaction(
(txn) async {
await txn.update(
_tableAksa,
updatedValues,
where: 'id = ?',
whereArgs: [id],
);
},
);
}
}
这是模型
class AndungJobModels with ChangeNotifier {
int? id;
int? fb;
int? yt;
int? shorts;
int? ig;
int? tiktok;
int? total;
int? targetFb;
int? targetYt;
int? targetShorts;
int? targetIg;
int? targetTiktok;
int? targetTotal;
String? date;
AndungJobModels({
this.id,
this.fb = 0,
this.yt = 0,
this.shorts = 0,
this.ig = 0,
this.tiktok = 0,
this.total = 0,
this.targetFb = 0,
this.targetYt = 0,
this.targetShorts = 0,
this.targetIg = 0,
this.targetTiktok = 0,
this.targetTotal = 0,
this.date,
}) {
hitungTotal();
}
void hitungTotal() {
total = (fb ?? 0) + (yt ?? 0) + (shorts ?? 0) + (ig ?? 0) + (tiktok ?? 0);
notifyListeners();
}
factory AndungJobModels.fromMap(Map<String, dynamic> map) => AndungJobModels(
id: map['id'],
fb: map['fb'],
targetFb: map['targetFb'],
yt: map['yt'],
targetYt: map['targetYt'],
shorts: map['shorts'],
targetShorts: map['targetShorts'],
ig: map['ig'],
targetIg: map['targetIg'],
tiktok: map['tiktok'],
targetTiktok: map['targetTiktok'],
total: map['total'],
targetTotal: map['targetTotal'],
date: map['date'],
);
Map<String, dynamic> toMap() => {
'id': id,
'fb': fb,
'targetFb': targetFb,
'yt': yt,
'targetYt': targetYt,
'shorts': shorts,
'targetShorts': targetShorts,
'ig': ig,
'targetIg': targetIg,
'tiktok': tiktok,
'targetTiktok': targetTiktok,
'total': total,
'targetTotal': targetTotal,
'date': date,
};
}
这是我添加并使数据库锁定发生的代码
class RekapAndung extends StatelessWidget {
const RekapAndung({super.key});
@override
Widget build(BuildContext context) {
int totalFbAndung = 0;
int totalYtAndung = 0;
int totalShortsAndung = 0;
int totalIgAndung = 0;
int totalTiktokAndung = 0;
int totalAkhir = 0;
final andungProvider = Provider.of<AndungJobProvider>(context);
return FutureBuilder<List<AndungJobModels>>(
future: andungProvider.loadAndungData(),
builder: (context, snapshot) {
var dataAndung = snapshot.data;
if (dataAndung != null) {
for (int i = 0; i < dataAndung.length; i++) {
totalFbAndung += dataAndung[i].fb ?? 0;
totalYtAndung += dataAndung[i].yt ?? 0;
totalShortsAndung += dataAndung[i].shorts ?? 0;
totalIgAndung += dataAndung[i].ig ?? 0;
totalTiktokAndung += dataAndung[i].tiktok ?? 0;
}
}
totalAkhir = totalFbAndung +
totalYtAndung +
totalShortsAndung +
totalIgAndung +
totalTiktokAndung;
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: const Offset(0, 0),
color:
Color.fromARGB(0.25.toInt(), 0, 0, 0).withOpacity(0.2),
blurRadius: 1,
spreadRadius: 1,
),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (dataAndung != null && dataAndung.isNotEmpty)
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: [
TextSpan(
text:
dataAndung[0].date ?? "Tanggal Belumm Dipilih",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: dataAndung[0].date == null
? Colors.red
: null,
),
),
const TextSpan(
text: "\nhingga\n",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF1570EF),
),
),
TextSpan(
text: dataAndung[dataAndung.length - 1].date ??
"Tanggal Belum Dipilih!",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color:
dataAndung[dataAndung.length - 1].date == null
? Colors.red
: null,
),
),
],
),
),
const Divider(thickness: 1.5),
SosmedWidget(
type: "Row",
sosmed: "Facebook",
imagePath: 'assets/images/fb.png',
value: totalFbAndung,
),
SosmedWidget(
type: "Row",
sosmed: "Youtube",
imagePath: 'assets/images/yt.png',
value: totalYtAndung,
),
SosmedWidget(
type: "Row",
sosmed: "Shorts",
imagePath: 'assets/images/shorts.png',
value: totalShortsAndung,
),
SosmedWidget(
type: "Row",
sosmed: "Instagram",
imagePath: 'assets/images/ig.png',
value: totalIgAndung,
),
SosmedWidget(
type: "Row",
sosmed: "TikTok",
imagePath: 'assets/images/tiktok.png',
value: totalTiktokAndung,
),
const Divider(thickness: 1.5),
const Text(
"Total",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
),
),
Text(
"$totalAkhir",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
),
),
],
),
),
);
}
return Container();
},
);
}
}
调试控制台
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 12 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 1223 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 47 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 817 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 796 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 19 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 68 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 12 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 236 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/chatty ( 6072): uid=10278(com.example.fajar_app) 1.ui identical 572 lines
2
I/flutter ( 6072): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
Lost connection to device.
如果代码像上面那样,如何解决锁定数据库问题?我认为问题出在 RekapAndung 类中,因为在我添加此类之前,所有代码都可以正常工作
这只是一个警告。您正在执行大量 SQL 查询。您可以使用
batch
,它可以帮助您。
batch = db.batch();
batch.insert('Test', {'name': 'item'});
batch.update('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']);
batch.delete('Test', where: 'name = ?', whereArgs: ['item']);
results = await batch.commit();
我建议你使用Hive。它速度很快,并且可以与 flutter 的
build
方法很好地配合。
Hive 的性能远远优于 SQLite 和 SharedPreferences 写入或删除。