211011 월
내 주말 어디갔징?
📌 이제 CRUD를 알아보자!
데이터 입력하기
📌 플로팅 버튼을 누르면 데이터 입력 화면으로 이동하고 저장하기를 누르면 데이터 베이스에 저장되도록 하자!
class _AddTodoApp extends State<AddTodoApp> {
TextEditingController? titleController;
TextEditingController? contentController;
@override
void initState() {
super.initState();
titleController = new TextEditingController();
contentController = new TextEditingController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todo 추가'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10),
child: TextField(
controller: titleController,
decoration: InputDecoration(labelText: '제목'),
),
),
Padding(
padding: EdgeInsets.all(10),
child: TextField(
controller: contentController,
decoration: InputDecoration(labelText: '할일'),
),
),
ElevatedButton(
onPressed: () {
Todo todo = Todo(
title: titleController!.value.text,
content: contentController!.value.text,
active: 0);
Navigator.of(context).pop(todo);
},
child: Text('저장하기'),
)
],
),
),
),
);
👉🏻 TextEditingController로 데이터를 입력하는 칸을 만든다.
✍🏻 pop 함수로 데이터를 메인에 전달한다.
void _insertTodo(Todo todo) async {
final Database database = await widget.db;
await database.insert('todos', todo.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace);
}
👉🏻 widget.db를 이용해 database 객체를 선언하고 insert함수로매개변수로 전달받은 데이터를 입력한다. todos라는 테이블에 데이터를 Map 형태로 바꿔준다.
✍🏻 widget.db를 이용하면 현재 State 상위에 있는 StatefulWidget에 있는 db 변수를 사용할 수 있다.
✍🏻 conflictAlgorithm은 충돌이 발생할 때를 대비한 것이다. id값이 충돌하면 replace로 새로운 데이터로 교체한다.
floatingActionButton: FloatingActionButton(
onPressed: () async {
final todo = await Navigator.of(context).pushNamed('/add');
if (todo != null) {
_insertTodo(todo as Todo);
}
},
👉🏻 플로팅 버튼에 _insert함수를 추가한다.
(영상)
데이터 검색하기
class _DatabaseApp extends State<DatabaseApp> {
Future<List<Todo>> getTodos() async {
final Database database = await widget.db;
final List<Map<String, dynamic>> maps = await database.query('todos');
return List.generate(maps.length, (i) {
int active = maps[i]['active'] == 1 ? 1 : 0;
return Todo(
title: maps[i]['title'].toString(),
content: maps[i]['content'].toStirng(),
active: active,
id: maps[i]['id']);
});
}
👉🏻 데이터를 가져오는 getTodos 함수를 만든다. maps 목록을 활동해 List.generate함수에서 할 일 목록에 표시할 각 아이템을 만든다.
class _DatabaseApp extends State<DatabaseApp> {
Future<List<Todo>>? todoList;
@override
void initState() {
super.initState();
todoList = getTodos();
}
👉🏻 할 일 목록은 따로 변수를 선언해 initState함수에서 호출한다.
body: Container(
child: Center(
child: FutureBuilder(
builder: (context, snapshot) {
switch(snapshot.connectionState) {
case ConnectionState.none:
return CircularProgressIndicator();
case ConnectionState.waiting:
return CircularProgressIndicator();
case ConnectionState.active:
return CircularProgressIndicator();
case ConnectionState.done:
if(snapshot.hasData) {
return ListView.builder(
itemBuilder: (context, index) {
Todo todo = (snapshot.data as List<Todo>)[index];
return Card(
child: Column(
children: <Widget>[
Text(todo.title!),
Text(todo.content!),
Text('${todo.active == 1 ? 'true' : 'false'}'),
],),
);
},
itemCount: (snapshot.data as List<Todo>).length,
);
} else {
return Text('No data');
}
}
return CircularProgressIndicator();
},
future: todoList,
),
),
),
👉🏻 서버에서 데이터를 받거나 파일에 데이터를 가져올 때 사용한다. switch문으로 데이터를 얼마나 가져왔는지 상태를 표시한다.
데이터 수정하기
return ListTile(
title: Text(
todo.title!,
style: TextStyle(fontSize: 20),
),
subtitle: Container(
child: Column(
children: <Widget>[
Text(todo.content!),
Text('체크 : ${todo.active == 1 ? 'true' : 'false'}'),
Container(
height: 1,
color: Colors.blue,
)
],
),
),
);
👉🏻 할 일 목록을 리스트 뷰로 꾸민다.
✍🏻 ListTile 위젯: title, subtitle, leading, trailing 옶션으로 위젯의 위치를 지정할 수 있다. / Card 위젯: 카드는 칸막이를 만들고 그 안에서 위젯을 자유롭게 꾸민다.
onTap: () async {
Todo result = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('${todo.id} : ${todo.title}'),
content: Text('Todo를 체크하시겠습니까?'),
actions: <Widget>[
TextButton(
onPressed: () {
setState(() {
todo.active == 1
? todo.active = 0
: todo.active = 1;
});
Navigator.of(context).pop(todo);
},
child: Text('예')),
TextButton(
onPressed: () {
Navigator.of(context).pop(todo);
},
child: Text('아니요')),
],
);
});
_updateTodo(result);
},
👉🏻 showDialog함수로 알림 창을 호출한다. 실제 알림창은 AlertDialog로 만든다.
✍🏻 FlatButton으로 예, 아니오 버튼을 만들고 pop함수로 데이터를 전달한다.
void _updateTodo(Todo todo) async {
final Database database = await widget.db;
await database.update(
'todos',
todo.toMap(),
where: 'id = ?',
whereArgs: [todo.id],
);
setState(() {
todoList = getTodos();
});
}
👉🏻 database.update함수로 데이터를 수정한다.
✍🏻 where와 whereArgs에 전달할 인자를 살펴보자. where는 어떤 데이터를 수정할 것인지 나타내고 id값으로 수정할 데이터를 찾는다. 매개변수 todo로 받은 데이터의 id값을 whereArgs에 설정하고 이 값으로 데이터 베이스에서 수정할 데이터를 찾는다.
onTap: () async {
TextEditingController controller =
new TextEditingController(text: todo.content);
Todo result = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('${todo.id} : ${todo.title}'),
content: TextField(
controller: controller,
keyboardType: TextInputType.text,
),
actions: <Widget>[
TextButton(
onPressed: () {
todo.active == 1
? todo.active = 0
: todo.active = 1;
todo.content =
controller.value.text;
Navigator.of(context).pop(todo);
},
child: Text('예')),
👉🏻 알림창 속의 내용을 수정하도록 텍스트 필드를 넣어 TextEditingController를 선언한다.
데이터 삭제하기
onLongPress: () async {
Todo result = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('${todo.id} : ${todo.title}'),
content: Text('${todo.content}를 삭제하시겠습니까?'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop(todo);
},
child: Text('예')),
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('아니요')),
],
);
}
);
_deleteTodo(result);
},
(...생략...)
void _deleteTodo(Todo todo) async {
final Database database = await widget.db;
await database.delete('todos', where: 'id=?', whereArgs: [todo.id]);
setState(() {
todoList = getTodos();
});
}
👉🏻 길게 누르면 삭제하는 _deleteTodo 함수가 발생한다.
✍🏻 onLongPress: 길게 터치할 때 발생하는 이벤트
✍🏻 getTodos 함수로 현재 목록을 새로 고침 한다.
'그 땐 App했지 > 그 땐 Flutter했지' 카테고리의 다른 글
[TAVE/Study]Do it! Flutter 10장 데이터베이스에 데이터 저장하기③ (0) | 2021.10.13 |
---|---|
[TAVE/Study]Do it! Flutter 10장 데이터베이스에 데이터 저장하기① (0) | 2021.10.13 |
[TAVE/Study]Do it! Flutter 9장 내부 저장소 이용하기② (0) | 2021.10.12 |
[TAVE/Study]Do it! Flutter 9장 내부 저장소 이용하기① (0) | 2021.10.11 |
[TAVE/Study]Do it! Flutter 8장 내비게이션 활용하기② (0) | 2021.10.06 |