我正在尝试学习如何在颤振中实现一个 moor 数据库,但我遇到了这个错误:
I/flutter ( 5303): Moor: Sent SELECT * FROM tasks; with args []
E/flutter ( 5303): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Unhandled error Null check operator used on a null value occurred in Instance of 'TodoBloc'.
E/flutter ( 5303): #0 $TasksTable.map
package:todo_app_orm/…/local/database.g.dart:153
E/flutter ( 5303): #1 MappedListIterable.elementAt (dart:_internal/iterable.dart:412:31)
E/flutter ( 5303): #2 ListIterator.moveNext (dart:_internal/iterable.dart:341:26)
E/flutter ( 5303): #3 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:188:27)
E/flutter ( 5303): #4 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
E/flutter ( 5303): #5 new List.of (dart:core-patch/array_patch.dart:50:28)
E/flutter ( 5303): #6 ListIterable.toList (dart:_internal/iterable.dart:212:44)
E/flutter ( 5303): #7 SimpleSelectStatement._mapResponse
package:moor/…/select/select.dart:70
在等待我从 moor 数据库获得的未来之后,我收到了这个错误。如果我只得到 Future 对象但只有在等待对象之后才会出现List<Task>
。它发生在等待todo_bloc.dart_database.getAllTasks()
中的此处之后:
class TodoBloc extends Bloc<TodoEvent, TodoState> {
TodoBloc(this._database) : super(TodoInitial());
final Database _database;
@override
Stream<TodoState> mapEventToState(
TodoEvent event,
) async* {
if (event is LoadTasks) {
List<Task> tasks = await _database.getAllTasks();
yield TasksUpdated(tasks);
}
if (event is AddTask) {
_database.insertTask(event.task);
final tasks = state.tasks;
yield TasksUpdated([...tasks, event.task]);
}
if (event is RemoveTask) {
await _database.deleteTask(event.task);
}
}
}
数据库.dart:
@UseRowClass(Task)
class Tasks extends Table {
TextColumn get id => text()();
TextColumn get title => text()();
BoolColumn get isHighPriority => boolean()();
Set<Column> get primaryKey => {id};
}
@UseMoor(tables: [Tasks])
class Database extends _$Database {
Database()
: super(FlutterQueryExecutor.inDatabaseFolder(
path: 'db.sqlite', logStatements: true));
@override
int get schemaVersion => 1;
Future<List<Task>> getAllTasks() => select(tasks).get();
Future insertTask(Task task) => into(tasks).insert(task);
Future deleteTask(Task task) => delete(tasks).delete(task);
}
任务飞镖:
class Task implements Insertable<Task> {
Task({
required this.id,
required this.title,
this.isHighPriority = false,
});
final String id;
final String title;
final bool isHighPriority;
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
return TasksCompanion(
id: Value(id),
title: Value(title),
isHighPriority: Value(isHighPriority),
).toColumns(nullToAbsent);
}
}
数据库.g.dart:
class TasksCompanion extends UpdateCompanion<Task> {
final Value<String> id;
final Value<String> title;
final Value<bool> isHighPriority;
const TasksCompanion({
this.id = const Value.absent(),
this.title = const Value.absent(),
this.isHighPriority = const Value.absent(),
});
TasksCompanion.insert({
required String id,
required String title,
required bool isHighPriority,
}) : id = Value(id),
title = Value(title),
isHighPriority = Value(isHighPriority);
static Insertable<Task> custom({
Expression<String>? id,
Expression<String>? title,
Expression<bool>? isHighPriority,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
if (title != null) 'title': title,
if (isHighPriority != null) 'is_high_priority': isHighPriority,
});
}
TasksCompanion copyWith(
{Value<String>? id, Value<String>? title, Value<bool>? isHighPriority}) {
return TasksCompanion(
id: id ?? this.id,
title: title ?? this.title,
isHighPriority: isHighPriority ?? this.isHighPriority,
);
}
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (id.present) {
map['id'] = Variable<String>(id.value);
}
if (title.present) {
map['title'] = Variable<String>(title.value);
}
if (isHighPriority.present) {
map['is_high_priority'] = Variable<bool>(isHighPriority.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('TasksCompanion(')
..write('id: $id, ')
..write('title: $title, ')
..write('isHighPriority: $isHighPriority')
..write(')'))
.toString();
}
}
class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
final GeneratedDatabase _db;
final String? _alias;
$TasksTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedTextColumn id = _constructId();
GeneratedTextColumn _constructId() {
return GeneratedTextColumn(
'id',
$tableName,
false,
);
}
final VerificationMeta _titleMeta = const VerificationMeta('title');
@override
late final GeneratedTextColumn title = _constructTitle();
GeneratedTextColumn _constructTitle() {
return GeneratedTextColumn(
'title',
$tableName,
false,
);
}
final VerificationMeta _isHighPriorityMeta =
const VerificationMeta('isHighPriority');
@override
late final GeneratedBoolColumn isHighPriority = _constructIsHighPriority();
GeneratedBoolColumn _constructIsHighPriority() {
return GeneratedBoolColumn(
'is_high_priority',
$tableName,
false,
);
}
@override
List<GeneratedColumn> get $columns => [id, title, isHighPriority];
@override
$TasksTable get asDslTable => this;
@override
String get $tableName => _alias ?? 'tasks';
@override
final String actualTableName = 'tasks';
@override
VerificationContext validateIntegrity(Insertable<Task> instance,
{bool isInserting = false}) {
final context = VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
} else if (isInserting) {
context.missing(_idMeta);
}
if (data.containsKey('title')) {
context.handle(
_titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta));
} else if (isInserting) {
context.missing(_titleMeta);
}
if (data.containsKey('is_high_priority')) {
context.handle(
_isHighPriorityMeta,
isHighPriority.isAcceptableOrUnknown(
data['is_high_priority']!, _isHighPriorityMeta));
} else if (isInserting) {
context.missing(_isHighPriorityMeta);
}
return context;
}
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Task map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Task(
id: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
title: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}title'])!,
isHighPriority: const BoolType()
.mapFromDatabaseResponse(data['${effectivePrefix}is_high_priority'])!,
);
}
@override
$TasksTable createAlias(String alias) {
return $TasksTable(_db, alias);
}
}
abstract class _$Database extends GeneratedDatabase {
_$Database(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
late final $TasksTable tasks = $TasksTable(this);
@override
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities => [tasks];
}
谁能看到问题出在哪里?如果需要,我可以提供更多信息。