728x90

학습목표


1. Firebase firestore CRUD 구현 및 테스트

내 알람 추가 기능을 위주로 firebase firestore에 데이터 쓰기/읽기/수정/삭제 구현해보기

 

회고


 

1. Firebase firestore CRUD 구현 및 테스트

내 알람 추가 기능을 위주로 firebase firestore에 데이터 쓰기/읽기/수정/삭제 구현해보기

 

alarm DB fields

alarmId : document.id로 대체

alarmTime 

alarmDay

alarmMemo

 

firestore 저장 화면

Oracle, MySQL 같은 relational database는 보통 테이블에 PK인 id를 지정하는데, Cloud Firestore는 NoSQL database이므로 collection안에 document.id로 document를 구분할 수 있다. 요일 정보와 시간 정보를 활용하여 알람이 울릴 시간을 지정할 수 있다. 

 

StreamBuilder를 사용하여 알람 정보를 실시간으로 가져오기

  // 위젯 빌드
  
  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;

    return Column(
      children: [
        // top bar
        topBar('내 알람'),

        Expanded(
            child: StreamBuilder<QuerySnapshot>(
          stream: Api('alarm').streamDataCollection(),
          builder:
              (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasData) {
              listMessage = snapshot.data!.docs;
              if (listMessage.length > 0) {
                return ListView.builder(
                  itemBuilder: (context, index) =>
                      buildItem(index, snapshot.data?.docs[index]),
                  itemCount: snapshot.data?.docs.length,
                  reverse: false,
                  controller: listScrollController,
                );
              } else {
                return Center(child: Text("알람이 없습니다."));
              }
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        )),
      ],
    );
  }
  
    // 각각의 알람
    Widget buildItem(int index, DocumentSnapshot? document) {
        Map<String, dynamic> routine = document!.get('alarmDay');
        List alarmDayString = [];
        for (final mapEntry in routine.entries) {
          final key = mapEntry.key;
          final value = mapEntry.value;
          if (value == true) {
            alarmDayString.add(key);
          }
        }

        return Alarm(
            id: document.id,
            height: MediaQuery.of(context).size.height,
            time: document.get('alarmTime'),
            group: document.get('alarmMemo'),
            day: alarmDayString.join(', '),
            memo: document.get('alarmMemo'),
            remaining: "남은시간");
    }

서버에서 데이터를 렌더링할 때 보통 FutureBuilder와 StreamBuilder를 사용한다. FutureBuilder는 화면에 접근할 때 한 번 가져온다. StreamBuilder는 한 화면에서 데이터가 변경될 때마다 실시간으로 반영된다. 일단 즉각적으로 변경을 확인하고 싶어서 StreamBuilder를 사용하였다.

 

QuerySnapshot, DocumentSnapshot을 가져오거나 추가, 삭제, 수정하는 함수

// firestore crud

import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';

class Api {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  final String path;

  Api(this.path);

  Future<QuerySnapshot> getDataCollection() {
    return _db
        .collection(path)
        .get(); //Futuer Return single result over a period of time
  }

  Stream<QuerySnapshot> streamDataCollection() {
    return _db
        .collection(path)
        .snapshots(); // Stream Return multiple values over a period of time
  }

  Future<DocumentSnapshot> getDocumentById(String id) {
    return _db.collection(path).doc(id).get();
  }

  Future<void> removeDocument(String id) {
    return _db.collection(path).doc(id).delete();
  }

  Future<DocumentReference> addDocument(Map<String, Object> data) {
    return _db.collection(path).add(data);
  }

  Future<void> updateDocument(Map<String, Object> data, String id) {
    return _db.collection(path).doc(id).update(data);
  }
}

document를 추가할 때 id를 자동 생성해준다. 수정, 삭제는 id를 기준으로 수행한다. 전체 데이터 조회는 QuerySnapshot으로 받는다.

 

기능 시연 영상

https://youtu.be/B48QjVuWYTQ

 

 

+ Recent posts