1

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

警告(moor):看起来您已经多次创建了数据库类AppDatabase。当这两个数据库使用相同的 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);
}

主要飞镖:

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

提前致谢!

4

1 回答 1

2

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

于 2021-02-04T06:54:20.807 回答