drift
由moor改名 Flutter 数据库moor的正确使用姿势
1. 添加依赖
environment:
sdk: '>=2.19.2 <3.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
drift: ^2.8.0
drift_db_viewer: ^2.0.0
sqlite3_flutter_libs: ^0.5.18
path_provider: ^2.1.1
path: ^1.8.2
dev_dependencies:
flutter_test:
sdk: flutter
drift_dev: ^2.8.3
2. 编写数据库
import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
part 'my_database.g.dart';
class Tasks extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text().withLength(min: 1, max: 50)();
BoolColumn get completed => boolean().withDefault(const Constant(false))();
}
@DriftDatabase(tables: [Tasks])
class MyDatabase extends _$MyDatabase {
MyDatabase() : super(openConnection());
@override
int get schemaVersion => 1;
///插入
Future<int> insertTask(Task task) async {
return await into(tasks).insert(task);
}
///查询数据
Future<List<Task>> queryTasks() async {
return await select(tasks).get();
}
/// 更新数据
Future<bool> updateTask(Task task) async {
return await update(tasks).replace(task);
}
///删除数据
Future<int> deleteTask(Task task) async {
return await delete(tasks).delete(task);
}
///删除数据
Future<int> deleteAllTasks() => delete(tasks).go();
}
class DatabaseManager {
MyDatabase myDatabase = MyDatabase();
DatabaseManager._();
static final DatabaseManager _instance = DatabaseManager._();
static DatabaseManager get instance {
return _instance;
}
}
LazyDatabase openConnection() {
return LazyDatabase(() async {
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'test.db'));
return NativeDatabase(file);
});
}
3. 执行命令生成代码
flutter pub run build_runner build --delete-conflicting-outputs
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'my_database.dart';
// ignore_for_file: type=lint
class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
@override
final GeneratedDatabase attachedDatabase;
final String? _alias;
$TasksTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedColumn<int> id = GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
static const VerificationMeta _nameMeta = const VerificationMeta('name');
@override
late final GeneratedColumn<String> name = GeneratedColumn<String>(
'name', aliasedName, false,
additionalChecks:
GeneratedColumn.checkTextLength(minTextLength: 1, maxTextLength: 50),
type: DriftSqlType.string,
requiredDuringInsert: true);
static const VerificationMeta _completedMeta =
const VerificationMeta('completed');
@override
late final GeneratedColumn<bool> completed =
GeneratedColumn<bool>('completed', aliasedName, false,
type: DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({
SqlDialect.sqlite: 'CHECK ("completed" IN (0, 1))',
SqlDialect.mysql: '',
SqlDialect.postgres: '',
}),
defaultValue: const Constant(false));
@override
List<GeneratedColumn> get $columns => [id, name, completed];
@override
String get aliasedName => _alias ?? 'tasks';
@override
String get 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));
}
if (data.containsKey('name')) {
context.handle(
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
} else if (isInserting) {
context.missing(_nameMeta);
}
if (data.containsKey('completed')) {
context.handle(_completedMeta,
completed.isAcceptableOrUnknown(data['completed']!, _completedMeta));
}
return context;
}
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Task map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return Task(
id: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
name: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}name'])!,
completed: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}completed'])!,
);
}
@override
$TasksTable createAlias(String alias) {
return $TasksTable(attachedDatabase, alias);
}
}
class Task extends DataClass implements Insertable<Task> {
final int id;
final String name;
final bool completed;
const Task({required this.id, required this.name, required this.completed});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<int>(id);
map['name'] = Variable<String>(name);
map['completed'] = Variable<bool>(completed);
return map;
}
TasksCompanion toCompanion(bool nullToAbsent) {
return TasksCompanion(
id: Value(id),
name: Value(name),
completed: Value(completed),
);
}
factory Task.fromJson(Map<String, dynamic> json,
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return Task(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
completed: serializer.fromJson<bool>(json['completed']),
);
}
@override
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'completed': serializer.toJson<bool>(completed),
};
}
Task copyWith({int? id, String? name, bool? completed}) => Task(
id: id ?? this.id,
name: name ?? this.name,
completed: completed ?? this.completed,
);
@override
String toString() {
return (StringBuffer('Task(')
..write('id: $id, ')
..write('name: $name, ')
..write('completed: $completed')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, completed);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is Task &&
other.id == this.id &&
other.name == this.name &&
other.completed == this.completed);
}
class TasksCompanion extends UpdateCompanion<Task> {
final Value<int> id;
final Value<String> name;
final Value<bool> completed;
const TasksCompanion({
this.id = const Value.absent(),
this.name = const Value.absent(),
this.completed = const Value.absent(),
});
TasksCompanion.insert({
this.id = const Value.absent(),
required String name,
this.completed = const Value.absent(),
}) : name = Value(name);
static Insertable<Task> custom({
Expression<int>? id,
Expression<String>? name,
Expression<bool>? completed,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
if (name != null) 'name': name,
if (completed != null) 'completed': completed,
});
}
TasksCompanion copyWith(
{Value<int>? id, Value<String>? name, Value<bool>? completed}) {
return TasksCompanion(
id: id ?? this.id,
name: name ?? this.name,
completed: completed ?? this.completed,
);
}
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (id.present) {
map['id'] = Variable<int>(id.value);
}
if (name.present) {
map['name'] = Variable<String>(name.value);
}
if (completed.present) {
map['completed'] = Variable<bool>(completed.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('TasksCompanion(')
..write('id: $id, ')
..write('name: $name, ')
..write('completed: $completed')
..write(')'))
.toString();
}
}
abstract class _$MyDatabase extends GeneratedDatabase {
_$MyDatabase(QueryExecutor e) : super(e);
late final $TasksTable tasks = $TasksTable(this);
@override
Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities => [tasks];
}
4. 调用
Future<void> add() async {
try {
await DatabaseManager.instance.myDatabase
.into(DatabaseManager.instance.myDatabase.tasks)
.insert(TasksCompanion.insert(name: "任务$current"));
current = current + 1;
var list = await DatabaseManager.instance.myDatabase.queryTasks();
tasks = list;
setState(() {});
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> delete(int i) async {
await DatabaseManager.instance.myDatabase.deleteTask(tasks[i]);
tasks.removeAt(i);
current = current - 1;
setState(() {});
}
Future<void> clear() async {
await DatabaseManager.instance.myDatabase.deleteAllTasks();
tasks.clear();
current = 0;
setState(() {});
}
5.查看数据库
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
DriftDbViewer(DatabaseManager.instance.myDatabase)));