Как остановить создание файла базы данных класса несколько раз при использовании flutter_moor?

#android #sql #flutter #dart #flutter-moor

#Android #sql #флаттер #dart #flutter-moor

Вопрос:

Всякий раз, когда я добавляю новую строку в свою базу данных в своем приложении flutter, я получаю эту ошибку :

ПРЕДУПРЕЖДЕНИЕ (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. Получатель: null Попытался вызвать: » (Фактическая ошибка содержит пару квадратных скобок, за которыми следует пара круглых скобок с нулем между круглыми скобками вместо кавычек)

Итак, я хочу избавиться от обеих этих ошибок, чтобы я мог начать интеграцию своих API

Заранее спасибо!

Ответ №1:

Вы не должны вызывать AppDatabase() более одного раза в своем приложении. AppDatabase() Каждый раз при вызове создается новый экземпляр, и в итоге получается много экземпляров базы данных. Лучший способ сделать это — создать его один раз и предоставить его необходимым компонентам. Кроме того, проверьте шаблон Singleton в Dart.