如何在使用flutter_moor时多次创建类数据库文件?



每当我在我的flutter应用程序中添加新行到我的数据库时,我都会得到此错误:

WARNING (moor):看起来您已经多次创建了数据库classAppDatabase。当这两个数据库使用相同的QueryExecutor时,将出现竞争条件,并可能破坏数据库。

我阅读了不同的文章,并推断出我可能不止一次地调用了构造函数,但仍然没有找到解决方法。

下面是一些初始引用的代码片段:

pubspec.yaml:

dependencies:
flutter:
sdk: flutter
basic_utils: ^2.6.3
cupertino_icons: ^1.0.0
flutter_blue: ^0.7.3
google_fonts: ^1.1.1
http: ^0.12.2
json_annotation: ^3.1.1
logging: ^0.11.4
#moor: ^3.4.0
moor_flutter: ^3.1.0
provider: ^4.3.3
sqflite: ^1.3.2+3
sqlite3_flutter_libs: ^0.3.0
url_launcher: ^5.7.10
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.9.0
chopper_generator: ^3.0.4
json_serializable: ^3.3.0
moor_generator: ^3.4.1

moor_database.dart:

import 'package:moor_flutter/moor_flutter.dart';
part 'moor_database.g.dart';
@DataClassName('AvailableFunctionTable') //Final Table Name
class AvailableFunctionsTable extends Table {
IntColumn get id => integer()();
TextColumn get make => text().withLength(min: 1, max: 50)();
TextColumn get model => text().withLength(min: 1, max: 50).nullable()();
IntColumn get year => integer().nullable()();
TextColumn get functionType => text().withLength(min: 1, max: 100)();
TextColumn get functionName => text().withLength(min: 1, max: 100)();
@override
Set<Column> get primaryKey => {id};
}
@UseMoor(tables: [AvailableFunctionsTable])
class AppDatabase extends _$AppDatabase {
AppDatabase()
: super(FlutterQueryExecutor.inDatabaseFolder(
path: "db.sqlite", logStatements: true));
int get schemaVersion => 1;
Future<List<AvailableFunctionTable>> getAllAvailableFunctionss() =>
select(availableFunctionsTable).get();
Stream<List<AvailableFunctionTable>> watchAllAvailableFunctionss() =>
select(availableFunctionsTable).watch();
Future insertAvailableFunctions(AvailableFunctionTable availableFunctions) =>
into(availableFunctionsTable).insert(availableFunctions);
Future updateAvailableFunctions(AvailableFunctionTable availableFunctions) =>
update(availableFunctionsTable).replace(availableFunctions);
Future deleteAvailableFunctions(AvailableFunctionTable availableFunctions) =>
delete(availableFunctionsTable).delete(availableFunctions);
}

main.dart:

void main() {
runApp(AvFunctionsScreen());
}
class AvFunctionsScreen extends StatefulWidget {
@override
_AvFunctionsScreenState createState() => _AvFunctionsScreenState();
}
class _AvFunctionsScreenState extends State<AvFunctionsScreen> {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: Scaffold(
appBar: AppBar(
title: Text("AvFunctionsScreen List"),
),
body: SingleChildScrollView(child: NewEntry()),
),
);
}
}
class NewEntry extends StatefulWidget {
@override
_NewEntryState createState() => _NewEntryState();
}
class _NewEntryState extends State<NewEntry> {
TextEditingController idController = TextEditingController();
TextEditingController makeController = TextEditingController();
TextEditingController modelController = TextEditingController();
TextEditingController functionNameController = TextEditingController();
TextEditingController functionTypeController = TextEditingController();
TextEditingController yearController = TextEditingController();
bool isloading = false;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: 'id'),
keyboardType: TextInputType.number,
controller: idController,
),
TextField(
decoration: InputDecoration(hintText: 'make'),
keyboardType: TextInputType.text,
controller: makeController,
),
TextField(
decoration: InputDecoration(hintText: 'model'),
keyboardType: TextInputType.text,
controller: modelController,
),
TextField(
decoration: InputDecoration(hintText: 'year'),
keyboardType: TextInputType.number,
controller: yearController,
),
TextField(
decoration: InputDecoration(hintText: 'func type'),
keyboardType: TextInputType.text,
controller: functionTypeController,
),
TextField(
decoration: InputDecoration(hintText: 'func name'),
keyboardType: TextInputType.text,
controller: functionNameController,
),
RaisedButton(
onPressed: () {
setState(() {
AppDatabase().insertAvailableFunctions(AvailableFunctionTable(
id: int.parse(idController.text),
make: makeController.text,
model: modelController.text,
year: int.parse(yearController.text),
functionName: functionNameController.text,
functionType: functionTypeController.text,
));
idController.clear();
makeController.clear();
modelController.clear();
yearController.clear();
functionNameController.clear();
functionTypeController.clear();
});
},
color: Colors.green,
child: Text("Add info"),
),
Container(
height: 700,
width: double.infinity,
child: StreamBuilder(
stream: AppDatabase().watchAllAvailableFunctionss(),
builder: (context,
AsyncSnapshot<List<AvailableFunctionTable>> snapshot) {
return ListView.builder(
itemBuilder: (_, index) {
return Card(
color: Colors.blueAccent,
child: ListTile(
leading: CircleAvatar(
child: Text('${index + 1}'),
radius: 20,
),
title: Text(snapshot.data[index].id.toString() +
' ' +
snapshot.data[index].year.toString()),
subtitle: Text(snapshot.data[index].make +
' ' +
snapshot.data[index].model +
' ' +
snapshot.data[index].functionType +
' ' +
snapshot.data[index].functionName),
trailing: IconButton(
icon: Icon(Icons.delete_outline),
onPressed: () {
setState(() {
AppDatabase().deleteAvailableFunctions(
snapshot.data[index]);
});
},
color: Colors.red,
)),
);
},
itemCount: snapshot?.data?.length,
);
},
),
)
],
);
}
}

虽然我得到我的输出很好,应用程序似乎工作,它给我一个错误在调试控制台每次热重启:

方法'[]'被调用为null。接收器:零(实际的错误是一对方括号后面跟着一对圆括号,圆括号之间有一个零,而不是引号)

我想去掉这两个错误这样我就可以开始集成我的api了

提前感谢!

您不应该在应用程序中多次调用AppDatabase()。每次调用AppDatabase()都会创建一个新实例,最终得到许多数据库实例。最好的方法是创建它一次,并将其提供给所需的组件。另外,检查单例pattern in Dart.

最新更新