簡體   English   中英

Flutter Riverpod 和 Firebase

[英]Flutter Riverpod and Firebase

我一直在研究一些使用 riverpod 的示例,試圖正確地將邏輯與 UI 層和業務層分開。 在這種情況下,我的用例是我想在 Firestore 中存儲自定義用戶配置文件,但是當涉及 ViewModel 時,我對提供程序設置感到困惑。

來自codewithandrea.com的示例為每個屏幕定義了兩個文件,一個 model (ProfileModel) 和一個頁面/頁面構建器 (ProfilePageBuilder)。 在 ProfilePageBuilder 的頂部,它聲明了一個 state 提供程序來訪問 ViewModel。 該提供程序解析 ProfileModel 所需的依賴項。

final profileModelProvider =
    StateNotifierProvider.autoDispose<ProfileModel, ProfileState>((ref) {
  final authService = ref.watch(authServiceProvider);

  final databaseService = ref.watch(databaseProvider)!;

  return ProfileModel(
      authService: authService, databaseService: databaseService);
});

現在,我希望頁面能夠訪問從 Firestore 返回的用戶配置文件,但 Firestore 服務返回一個Stream<UserProfile> 我的問題是:

  • 我是否將 stream 解析為未來並在調用頁面中的方法時返回配置文件,例如 initState 中的 loadProfile()。
  • 或者我是否在鏈接到 Firestore 服務的 PageBuilder 中創建一個新的 stream 提供程序(我覺得這不符合架構)
  • 我是否從 ViewModel 將 stream 作為 stream 返回,然后創建一個查看 ViewModel 而不是服務的 stream 提供程序?

這是 Firebase 和 Riverpod 的常見問題。

是否要返回 stream 取決於您。 你不必。 這是決定你想要什么的思路。

  • 如果 UI 應該知道“先前”值,您可能應該返回 stream。
  • 如果 UI 只關心“當前”值,則不必返回 stream。
  • 您可以使用有狀態小部件跟蹤最后一個值,因此您可能只需要當前值。

我將使用帶有代碼生成語法的 riverpod 2.0,但如果您願意,這些都可以在沒有 codegen 的情況下編寫,只是更冗長。

一種方法是使用來自package:rxdart的 BehaviorSubject,它只記住 stream 的最后一個值。

import 'package:rxdart/rxdart.dart';

@riverpod
BehaviorSubject<UserProfile> userProfileSubject(
       UserProfileStreamRef ref, 
       String userId, 
       /*more params if you want*/) {

   final firebaseStream = ...

   // goal of this provider is to get the stream
   // from firebase and convert to a BehaviorSubject
   return BehaviorSubject()
           ..addStream(firebaseStream);
}

@riverpod
UserProfile? userProfile(UserProfileRef ref) {
   // this provider listens to the behavior subject
   // and refreshes itself when the value changes
   // so the dependent providers and widgets can react
   final subject = ref.watch(userProfileSubjectProvider(userId, ...));


   // if no params to provider
   //final subject = ref.watch(userProfileSubjectProvider);

   // when there's a new value, invalidate self
   // so we re-run this and return the new value
   subject.doOnData((newProfile) {ref.invalidateSelf();});

   // note that subject can have a null value until
   // first value is emitted from the stream or stream emits a null.
   // your UI must handle this case.
   return subject.value;
}

現在您的視圖 model 或任何可以依賴於此userProfileProvider或直接在ConsumerWidget中使用它的視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM