Firestore를 사용하여 To-Do 앱을 만드는 방법을 설명하겠습니다. 이 예제에서는 Firebase Firestore를 사용하여 할 일 데이터를 저장하고, 읽고, 업데이트하고, 삭제하는 기능을 구현합니다.
1. firebase 내 데이터베이스 만들기
위와 같이 firestore 를 생성해줍니다.
1. 프로젝트 설정
pubspec.yaml 파일 업데이트
최신 Firebase 패키지를 pubspec.yaml 파일에 추가합니다.
dependencies:
flutter:
sdk: flutter
firebase_core:
firebase_auth:
cloud_firestore:
2. Firebase 설정
google-services.json 파일을 다운로드하여 android/app 디렉토리에 복사합니다. Firebase 콘솔에서 프로젝트를 설정하고 앱을 등록한 후 이 파일을 받을 수 있습니다.
android/build.gradle 파일 업데이트
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.0.0'
classpath 'com.google.gms:google-services:4.4.2'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
android/app/build.gradle 파일 업데이트
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 34
defaultConfig {
applicationId "com.example.flutter_todo"
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.2.2')
}
apply plugin: 'com.google.gms.google-services'
3. Firebase 초기화
main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'screens/todo_list_screen.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Firebase Todo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TodoListScreen(),
);
}
}
4. Firestore 데이터 모델
models/todo.dart
class Todo {
final String id;
final String title;
final bool isDone;
Todo({
required this.id,
required this.title,
this.isDone = false,
});
factory Todo.fromMap(Map<String, dynamic> data, String documentId) {
return Todo(
id: documentId,
title: data['title'] ?? '',
isDone: data['isDone'] ?? false,
);
}
Map<String, dynamic> toMap() {
return {
'title': title,
'isDone': isDone,
};
}
}
5. Firestore 서비스
services/firestore_service.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/todo.dart';
class FirestoreService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
Stream<List<Todo>> getTodos() {
return _db.collection('todos').snapshots().map((snapshot) =>
snapshot.docs.map((doc) => Todo.fromMap(doc.data(), doc.id)).toList());
}
Future<void> addTodo(Todo todo) {
return _db.collection('todos').add(todo.toMap());
}
Future<void> updateTodo(Todo todo) {
return _db.collection('todos').doc(todo.id).update(todo.toMap());
}
Future<void> deleteTodo(String id) {
return _db.collection('todos').doc(id).delete();
}
}
6. 프로바이더 설정
providers/todo_provider.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/todo.dart';
import '../services/firestore_service.dart';
class TodoProvider with ChangeNotifier {
final FirestoreService _firestoreService = FirestoreService();
late Stream<List<Todo>> _todos;
Stream<List<Todo>> get todos => _todos;
TodoProvider() {
_todos = _firestoreService.getTodos();
}
Future<void> addTodo(Todo todo) async {
await _firestoreService.addTodo(todo);
}
Future<void> updateTodo(Todo todo) async {
await _firestoreService.updateTodo(todo);
}
Future<void> deleteTodo(String id) async {
await _firestoreService.deleteTodo(id);
}
}
7. UI 작성
screens/todo_list_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/todo.dart';
import '../providers/todo_provider.dart';
import 'edit_todo_screen.dart';
class TodoListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('To-Do List'),
),
body: StreamBuilder<List<Todo>>(
stream: Provider.of<TodoProvider>(context).todos,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
final todos = snapshot.data!;
return ListView.builder(
itemCount: todos.length,
itemBuilder: (ctx, i) => ListTile(
title: Text(todos[i].title),
trailing: Checkbox(
value: todos[i].isDone,
onChanged: (value) {
Provider.of<TodoProvider>(context, listen: false).updateTodo(
Todo(
id: todos[i].id,
title: todos[i].title,
isDone: value!,
),
);
},
),
onLongPress: () {
Provider.of<TodoProvider>(context, listen: false)
.deleteTodo(todos[i].id);
},
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => EditTodoScreen(todo: todos[i]),
),
);
},
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (ctx) {
TextEditingController controller = TextEditingController();
return AlertDialog(
title: Text('Add Todo'),
content: TextField(
controller: controller,
decoration: InputDecoration(labelText: 'Title'),
),
actions: [
TextButton(
onPressed: () {
if (controller.text.isNotEmpty) {
final newTodo = Todo(
id: '',
title: controller.text,
);
Provider.of<TodoProvider>(context, listen: false)
.addTodo(newTodo);
Navigator.of(ctx).pop();
}
},
child: Text('Add'),
),
],
);
},
);
},
child: Icon(Icons.add),
),
);
}
}
screens/edit_todo_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/todo.dart';
import '../providers/todo_provider.dart';
class EditTodoScreen extends StatelessWidget {
final Todo todo;
EditTodoScreen({required this.todo});
@override
Widget build(BuildContext context) {
TextEditingController titleController = TextEditingController(text: todo.title);
return Scaffold(
appBar: AppBar(
title: Text('Edit Todo'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: titleController,
decoration: InputDecoration(labelText: 'Title'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (titleController.text.isNotEmpty) {
final updatedTodo = Todo(
id: todo.id,
title: titleController.text,
isDone: todo.isDone,
);
Provider.of<TodoProvider>(context, listen: false)
.updateTodo(updatedTodo);
Navigator.of(context).pop();
}
},
child: Text('Update'),
),
],
),
),
);
}
}
요약
1. Firestore 데이터 모델(Todo)을 정의합니다.
2. Firestore 서비스(FirestoreService)를 작성하여 Firestore와 상호작용합니다.
3. 프로바이더(TodoProvider)를 작성하여 상태 관리를 합니다.
4. UI를 작성하여 할 일 목록을 표시하고 추가, 수정, 삭제 기능을 구현합니다.
5. Firebase를 초기화하고 앱을 실행합니다.
이제 Firestore를 사용하여 할 일 데이터를 관리하는 간단한 To-Do 앱이 완성되었습니다. 필요에 따라 추가 기능을 구현하거나 UI를 개선할 수 있습니다.
'프론트엔드 > Flutter' 카테고리의 다른 글
flutter 디자인 패턴 모음 (0) | 2024.07.28 |
---|---|
flutter future 키워드 및 aysnc await 를 통한 비동기처리 (0) | 2024.07.28 |
flutter SQLite 데이터베이스 저장 (1) | 2024.07.25 |
flutter에서 바텀 네비게이션 바(Bottom Navigation Bar) (0) | 2024.07.24 |
flutter 주요 버튼 위젯 모음 (1) | 2024.07.24 |