이 글은 '11가지 앱을 만들며 배우는 크로스 플랫폼 앱개발 플러터 프로젝트' 라는 교재를 바탕으로 쓴 필기노트입니다.
객체 지향 프로그래밍에서 데이터베이스를 처리할 때는 일반적으로 데이터베이스의 테이블 구조를 미러링하는 객체를 생성한다. 그러면 코드가 더 안정적이고, 읽기 쉽고, 데이터 불일치를 막을 수 있다.
class ShoppingList {
int id;
String name;
int priority;
//생성자
ShoppingList(this.id, this.name, this.priority);
Map<String, dynamic> toMap() { //String(키), dynamic(값) 타입의 Map 반환
return {
'id' : (id==0)? null:id,
'name': name,
'priority': priority,
};
}
}
데이터베이스에서 새 레코드를 삽입할 때, null값을 입력하면 데이터베이스는 자동 증가 로직을 사용하여 새 값을 자동으로 할당한다. 이것이 id에 삼항연산자를 사용하는 이유이다. id가 0이면 이것을 null로 변경해서 SQLite가 id를 설정할 수 있도록 한다.
class ListItem {
int id;
int idList;
String name;
String quantity;
String note;
ListItem(this.id, this.idList, this.name, this.quantity, this.note);
Map<String, dynamic> toMap() {
return {
'id': (id==0)?null:id,
'idList': idList,
'name': name,
'quantity': quantity,
'note': note
};
}
}
값이 0일 때 ID를 null로 만드는 동일한 삼항 연산자를 사용하여 String, dynamic 타입의 Map을 반환하는 toMap() 메서드를 만들어준다.
Future<int> insertList(ShoppingList list) async {
int id = await this.db!.insert(
'lists',
list.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
return id;
}
Future<int> insertItem(ListItem item) async {
int id = await db!.insert(
'items',
item.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
return id;
}
여기서 insert() 메서드는 아래처럼 세 개의 인수를 취하는 sqflite 라이브러리에 의해 노출되는 특정 헬퍼 메서드다. 비동기 메서드이므로 await 명령을 사용하여 호출한다.
int id = await db.insert( //insert 헬퍼 메서드 호출
'items', //테이블 이름 전달
item.toMap(), //삽입되는 데이터를 Map으로 전달
);
그리고 conflictAlgorithm은 동일한 레코드를 두 번 삽입하려고 할 때 따라야 하는 동작을 지정한다. 동일한 목록이 여러 번 삽입되거나, 이전 데이터가 함수에 전달된 새 목록으로 대체된다. 여기서는 대체되는 걸로 사용되는 것 같다.
main.dart 파일에서 맨 아래에 ShList라는 StatefulWidget을 만든다.
class ShList extends StatefulWidget {
const ShList({Key? key}) : super(key: key);
State<ShList> createState() => _ShListState();
}
class _ShListState extends State<ShList> {
DbHelper helper = DbHelper(); //DbHelper 클래스의 인스턴스 만들기
Future showData() async { //여기서는 두 메서드를 테스트하는 데 사용
await helper.openDb(); //데이터를 삽입하기 전에 데이터베이스가 열려있는지 학인.
ShoppingList list = ShoppingList(0, 'Bakery', 2);
int listId = await helper.insertList(list);
ListItem item = ListItem (0, listId, 'Bread', 'note', '1kg');
int itemId = await helper.insertItem(item);
print('List Id: ' + listId.toString());
print('Item Id: ' + listId.toString());
}
Widget build(BuildContext context) {
showData();
return Scaffold(
appBar: AppBar(title: Text('Shopping List')),
body: ShList(),
);
}
}
+) main.dart에서 저번에 적었던 MyApp 클래스의 build() 메서드에서의 다음 코드는 지금 필요없으므로 삭제해준다.
DbHelper helper = DbHelper();
helper.testDb();
I/flutter ( 4589): List Id: 2
I/flutter ( 4589): Item Id: 3
책에서는 이렇게 나온다고 되어있는데 저는 나오지 않았습니다. 이유는 더 찾아봐야 할 것 같습니다. 표시되는 숫자는 데이터베이스의 레코드 수에 따라 다를 수 있습니다.