[플러터] SQflite 모델 클래스 만들기

모선·2022년 11월 6일

Flutter

목록 보기
2/3
post-thumbnail

이 글은 '11가지 앱을 만들며 배우는 크로스 플랫폼 앱개발 플러터 프로젝트' 라는 교재를 바탕으로 쓴 필기노트입니다.

모델 클래스 만들기

객체 지향 프로그래밍에서 데이터베이스를 처리할 때는 일반적으로 데이터베이스의 테이블 구조를 미러링하는 객체를 생성한다. 그러면 코드가 더 안정적이고, 읽기 쉽고, 데이터 불일치를 막을 수 있다.

  1. models 패키지를 만든 후 shopping_list.dart 파일을 만든다.
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를 설정할 수 있도록 한다.

  1. models 패키지 안에 list_items.dart 파일을 만든다.
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() 메서드를 만들어준다.

  1. 이전 게시물에서 만들었던 dbHelper.dart 파일의 DbHelper 클래스 안에 lists 테이블과 items 테이블에 새 레코드를 삽입하는 insertList, insertItem 메서드를 만들어준다. insert 메서드가 삽입된 레코드의 ID를 반환하므로 int 타입의 Future를 반환한다.
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

책에서는 이렇게 나온다고 되어있는데 저는 나오지 않았습니다. 이유는 더 찾아봐야 할 것 같습니다. 표시되는 숫자는 데이터베이스의 레코드 수에 따라 다를 수 있습니다.

profile
https://hy5sun.tistory.com/ << 이사중

0개의 댓글