iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
Mobile Development

Flutter - 複製貼上到開發套件之旅系列 第 15

【第十五天 - Flutter 官方 CodeLab Get-To-Know 活動報名教學(下)】

前言

我很喜歡這篇 CodeLab,我自己認為,如果這篇的內容看得懂那 Provider 基本上都會了。

如果想要看這篇的成品什麼樣子,歡迎去 官方 CodeLab 看。

ApplicationProvider

接續 【第十四天 - Flutter 官方 CodeLab Get-To-Know 活動報名教學(上)】,直接進入主題介紹方法。

初始化

在使用 Firebase 的時候都需要初始化。

await Firebase.initializeApp();

FireStore 監聽資料

這邊是用來查看有幾個人參加報名的,不需要判斷有無登入,都需要有參與者的人數。
可以看到這裡,他去找尋 collection == attendees 並找尋底下的 attending 欄位 == true,並進行即時監聽資料。可以看到這裡,他去找尋 collection == attendees 並找尋底下的 attending 欄位 == true,並進行即時監聽資料。

https://ithelp.ithome.com.tw/upload/images/20210908/20134548WunVMoJAf1.png

    FirebaseFirestore.instance
        .collection('attendees')
        .where('attending', isEqualTo: true)
        .snapshots()
        .listen((snapshot) {
      _attendees = snapshot.docs.length;
      notifyListeners();
    });

這邊是先判斷使用者是否有登入
未登入

  • Subscription
  • 留言暫存的 list 清空
    已登入
  • 監聽聊天內容( collection == guestbook,並且照著 timestamp 由大到小排序,並讀取每一個 document 的資料
  • 取得現在登入者的參與狀況
    FirebaseFirestore.instance.collection('attendees').doc(user.uid),是表示他要去取得 attendees 的資料,並且 doc 的 id == user.uid(現在使用者 的 uid)
    https://ithelp.ithome.com.tw/upload/images/20210908/20134548LyMAqf7KOJ.pnghttps://ithelp.ithome.com.tw/upload/images/20210908/20134548CdK0o7YxVz.png
    // 監聽使用者使否有登入的資訊
    FirebaseAuth.instance.userChanges().listen((user) {
      // 更改後,使用者從無登入 -> 已經登入的狀態
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
        // StreamSubscription 監聽資訊
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .snapshots()
            .listen((snapshot) {
              // 先清空資料
          _guestBookMessages = [];
          snapshot.docs.forEach((document) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'].toString(),
                message: document.data()['text'].toString(),
              ),
            );
          });
          // 資料變動完後, rebuild 畫面
          notifyListeners();
        });
        // 監聽 attending 參加人數的資料
        _attendingSubscription = FirebaseFirestore.instance
            .collection('attendees')
            .doc(user.uid)
            .snapshots()
            .listen((snapshot) {
          if (snapshot.data() != null) {
            if (snapshot['attending']==true) {
              _attending = Attending.yes;
            } else {
              _attending = Attending.no;
            }
          } else {
            _attending = Attending.unknown;
          }
          notifyListeners();
        });
      } else {
        // 關閉監聽器
        _loginState = ApplicationLoginState.loggedOut;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
        _attendingSubscription?.cancel(); // new
      }
      notifyListeners();
    });
    ```
    # 更新參與者狀況
    這邊會去存入 `collection == attendees` 且 `document id == currentUser.uid`。
    存入資料都必須像這樣,是一個 `map` 的型態。
    ```dart
      /// 更新 firebase user 的參加狀態。
  /// 這邊更新後會觸發 firebase 的 userChanges().listen,然後信行 attending 的更新
  set attending(Attending attending) {
    final userDoc = FirebaseFirestore.instance
        .collection('attendees')
        .doc(FirebaseAuth.instance.currentUser!.uid);
    if (attending == Attending.yes) {
      var map = {'attending': true};
      userDoc.set(map);
    } else {
      var map = {'attending': false};
      userDoc.set(map);
    }
  }

更新留言資訊

  這邊會去存入 `collection == guestbook`,這邊沒有指定 `document` 的名稱,因此 `firebase` 會隨機產生。
存入資料都必須像這樣,是一個 map 的型態。
  /// 更新 firebase message 的留言狀態。
/// 這邊更新後會觸發 firebase 的 userChanges().listen,然後信行 attending 的更新
Future<DocumentReference> addMessageToGuestBook(String message) {
  if (_loginState != ApplicationLoginState.loggedIn) {
    throw Exception('Must be logged in');
  }
  var map = {
    'text': message,
    'timestamp': DateTime.now().millisecondsSinceEpoch,
    'name': FirebaseAuth.instance.currentUser!.displayName,
    'userId': FirebaseAuth.instance.currentUser!.uid,
  };
  return FirebaseFirestore.instance.collection('guestbook').add(map);
}

介紹 Firebase 的一些方法

他會返回可用於登錄給定的登錄方法列表,用戶(由其主要電子郵件地址標識)。當您支持多種身份驗證機制時,此方法很有用。如果找不到用戶,則返回一個空的 List。如果電子郵件地址無效則拋出 FirebaseAuthException不合規電郵

FirebaseAuth.instance.fetchSignInMethodsForEmail(email)

提供 eamil 的登入方式

FirebaseAuth.instance.signInWithEmailAndPassword

註冊

FirebaseAuth.instance
        .createUserWithEmailAndPassword(email: email, password: password);
FirebaseAuth.instance.signOut();

Consumer

Cosumer,他類似一個 View 的控制器,他有 Cosumer2Cosumer3 等等...,builder 裡面第一個參數是 context,第二個則是 model(ApplicationProvider 的 model),第三個則是 child

Consumer4 的範例

Consumer4<changeNotifier1, changeNotifier2, changeNotifier3, changeNotifier4>(
builder: (context, changeNotifier1, changeNotifier2, changeNotifier3, changeNotifier4,   child) {
   // return your widget
}
)

這邊的話,累是一個 View 的中轉站,從 ApplicationProvider 取得現在登入的狀態,和方法,在 Consumer 中轉站傳遞給自定義的 Authentication 元件,讓邏輯和畫面分離。並使用 callBack 的方式,讓 ApplicationProvider,Firebase 裡面的 exception 可以顯示在畫面上面。

          Consumer<ApplicationProvider>(
          builder: (context, appState, _) {
            return Authentication(
              email: appState.email,
              loginState: appState.loginState,
              startLoginFlow: appState.startLoginFlow,
              // 把邏輯寫在 provider 裡面。然後當 Widget 裡面觸發資料後
              verifyEmail: appState.verifyEmail,
              signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
              cancelRegistration: appState.cancelRegistration,
              registerAccount: appState.registerAccount,
              signOut: appState.signOut,
            )
            ;
          }
        ),

References

  • Get to know Firebase for Flutter

  • Flutter Codelab

    總結

    這篇雖然很長,但是只要看懂 providerAuthentication 元件、CallBack,整篇大約就會一目瞭然。
    初接觸 Firebase 的朋友,可能就要了解一下要怎麼連接 Firebase,還有 FireStore 怎麼使用,collectiondocumentuserID、還有一些即時更新的 listener,需要去熟悉他,希望大家可以在 Flutter 上有所成長~~


上一篇
【第十四天 - Flutter 官方 CodeLab Get-To-Know 活動報名教學(上)】
下一篇
【第十六天 - Flutter Google、Apple、FB Sign in 流程講解】
系列文
Flutter - 複製貼上到開發套件之旅30

尚未有邦友留言

立即登入留言