使用flutter_moor时如何停止多次创建类数据库文件?
Posted
技术标签:
【中文标题】使用flutter_moor时如何停止多次创建类数据库文件?【英文标题】:How to stop class database file getting created multiple times when using flutter_moor? 【发布时间】:2021-02-04 06:26:38 【问题描述】:每当我在我的颤振应用程序中向我的数据库添加新行时,我都会收到此错误:
警告(moor):您似乎已经多次创建了数据库类AppDatabase。当这两个数据库使用相同的 QueryExecutor 时,会出现竞争条件并可能损坏数据库。
我阅读了不同的文章并推断出我可能不止一次调用了构造函数,但仍然没有找到解决方法。
这里有一些代码sn-ps供初步参考:
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
提前致谢!
【问题讨论】:
【参考方案1】:您不应在应用程序中多次调用AppDatabase()
。每次调用AppDatabase()
都会创建一个新实例,最终会得到许多数据库实例。最好的方法是创建一次并将其提供给所需的组件。另外,检查 Dart 中的 Singleton 模式。
【讨论】:
以上是关于使用flutter_moor时如何停止多次创建类数据库文件?的主要内容,如果未能解决你的问题,请参考以下文章