Flutter/Package
[Flutter] Drift
찌김이
2022. 7. 25. 23:08
728x90
반응형
Flutter 에서 로컬 데이터베이스 패키지 중 하나인 Drift 에 대해서 포스팅합니다.
Drift 는 Sqlflite 와 다르게 ORM 방식의 데이터베이스 입니다.
ORM 은 Object Relational Mapping (객체-관계 매핑), 쉽게 말해서 객체와 관계형 데이터베이스의 데이터를 연결해주는 것을 말합니다.
Android 의 Room , Spring 의 JPA, Node.js 의 Sequelize 등을 써보신 분은 익숙할 것입니다.
pubspec.yaml
dependencies:
drift: ^1.7.1
path_provider: ^2.0.11
path: ^1.8.2
dev_dependencies:
build_runner: ^2.2.0
drift_dev: ^1.7.0
todos.dart
- 모델 클래스를 만들고 Table 을 상속해줍니다.
- 타입Column get 변수명 => 타입()(); 형태로 선언해줍니다.
- Sqlflite 와 다르게 Boolean 처리를 알아서 해줍니다.
import 'package:drift/drift.dart';
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text()();
BoolColumn get done => boolean()();
}
todo_db_helper.dart
- 로컬 DB 를 사용하게 해주는 Helper 클래스를 구현해줍니다.
import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:flutter_drift/todos.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
part 'todo_db_helper.g.dart';
@DriftDatabase(
tables: [Todos],
)
class TodoDbHelper extends _$TodoDbHelper {
TodoDbHelper() : super(_openConnection());
@override
int get schemaVersion => 1;
}
LazyDatabase _openConnection() {
return LazyDatabase(() async {
// path_provider 를 통해 앱의 저장위치 얻음
final dbFolder = await getApplicationDocumentsDirectory();
// 해당 경로에 파일 생성
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return NativeDatabase(file);
});
}
- 터미널에 아래 명령어를 넣어주어 todo_db_helper.g.dart 을 생성합니다.
flutter pub run build_runner build
- 생성이 완료 되었으면 todo_db_helper.dart 에 CRUD 코드를 넣어줍니다.
import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:flutter_drift/todos.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
part 'todo_db_helper.g.dart';
@DriftDatabase(
tables: [Todos],
)
class TodoDbHelper extends _$TodoDbHelper {
TodoDbHelper() : super(_openConnection());
@override
int get schemaVersion => 1;
Future<List<Todo>> findAll() =>
(select(todos)..orderBy([(t) => OrderingTerm.desc(t.id)])).get();
Future<int> insertTodo(TodosCompanion todo) => into(todos).insert(todo);
Future<int> updateTodo(Todo todo,) =>
(update(todos)..where((t) => t.id.equals(todo.id))).write(todo);
Future<int> deleteTodo(int id) =>
(delete(todos)..where((t) => t.id.equals(id))).go();
}
LazyDatabase _openConnection() {
return LazyDatabase(() async {
// path_provider 를 통해 앱의 저장위치 얻음
final dbFolder = await getApplicationDocumentsDirectory();
// 해당 경로에 파일 생성
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return NativeDatabase(file);
});
}
todo_screen.dart
- 예시 화면은 Sqlflite 와 동일하게 간단한 CRUD 만 동작하게 구현했습니다.
- FutureBuilder 를 이용하여 todo 목록 정보를 가져옵니다.
import 'package:drift/drift.dart';
import 'package:flutter/material.dart';
import 'package:flutter_drift/todo_db_helper.dart';
class DriftScreen extends StatefulWidget {
const DriftScreen({Key? key}) : super(key: key);
@override
State<DriftScreen> createState() => _DriftScreenState();
}
class _DriftScreenState extends State<DriftScreen> {
TodoDbHelper todoDbHelper = TodoDbHelper();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Drift Sample Page',
),
),
body: FutureBuilder<List<Todo>>(
future: todoDbHelper.findAll(),
builder: (context, snapshot) {
// loading
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
// empty
if (snapshot.data!.isEmpty) {
return const Center(
child: Text(
'Todo is empty',
style: TextStyle(
fontSize: 20.0,
),
),
);
}
return ListView(
children: snapshot.data!
.map(
(e) => ListTile(
title: Text('${e.title} ${e.id}'),
leading: updateBtn(e),
trailing: deleteBtn(e.id!),
),
)
.toList(),
);
},
),
floatingActionButton: addBtn(),
);
}
Widget deleteBtn(int id) => IconButton(
onPressed: () {
setState(() {
todoDbHelper.deleteTodo(id);
});
},
icon: const Icon(Icons.delete_forever),
);
Widget updateBtn(Todo todo) => IconButton(
onPressed: () {
setState(() {
var title =
todo.title.contains('update') ? 'title' : 'update title';
todoDbHelper.updateTodo(
Todo(
id : todo.id,
title: title,
done: false,
),
);
});
},
icon: const Icon(Icons.update_sharp),
);
FloatingActionButton addBtn() => FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
todoDbHelper.insertTodo(
TodosCompanion(
title: Value('title'),
done: Value(true),
),
);
});
},
);
}
728x90
반응형