簡體   English   中英

Flutter Firestore:具有初始數據的 FirestoreBuilder

[英]Flutter Firestore: FirestoreBuilder with initial data

我正在制作我的第一個 Flutter 應用程序,我遇到了一個問題,但沒有找到任何解決方案。

我有一個渲染 Firestore 文檔的視圖,有兩種方法可以到達那里:

  • 從我已經加載文檔的列表中
  • 來自附加 uid 為 arguments (args) 的動態鏈接

因此,為了在從鏈接到達時監聽文檔更改和加載數據,我使用了 FirestoreBuilder,如下所示:

    return FirestoreBuilder<EventDocumentSnapshot>(
        ref: eventsRef.doc(args.uid),
        builder: (context, AsyncSnapshot<EventDocumentSnapshot> snapshot, Widget? child) {
          if (!snapshot.hasData) {
            return Container();
          }
          Event? event = snapshot.requireData.data;
          
          return Scafold(); //Rest of my rendering code
        }
     );
       
 

當我已經有了數據但仍然在聽變化時,我如何避免第一次調用 Firebase? 主要問題是我的英雄 animation 因此無法正常工作。

我嘗試使用StreamBuilderinitialData參數,但由於它期望 stream 我不知道如何轉換我的數據。

好吧,經過多次嘗試我自己找到了解決方案,所以我添加了我的 Model object 作為 initialData,但讓我糾結的是如何在構建器中獲取數據。 您必須根據數據的來源調用不同的方法。

    return StreamBuilder(
        initialData: args.event
        ref: eventsRef.doc(args.uid),
        builder: (context, AsyncSnapshot<dynamic> snapshot) {
          // Here is the trick, when data is coming from initialData you only
          // need to call requireData to get your Model
          Event event = snapshot.requireData is EventDocumentSnapshot ? snapshot.requireData.data : snapshot.requireData;
          
          return Scafold(); //Rest of my rendering code
        }
     );

閱讀cloud_firestore 的文檔,您可以看到可以通過 snapshots() 獲取查詢中的 Stream

StreamBuilder<QuerySnapshot>(
  stream: Firestore.instance.collection('books').snapshots(),
  builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (!snapshot.hasData) return new Text('Loading...');
    return new ListView(
      children: snapshot.data.documents.map((DocumentSnapshot document) {
        return new ListTile(
          title: new Text(document['title']),
          subtitle: new Text(document['author']),
        );
      }).toList(),
    );
  },
);

這對您沒有幫助,但是使用 GetX 可以像這樣輕松實現:您不再需要 StreamBuilder。

//GetXcontroller
class pageController extends GetXcontroller {

... 

RxList<EventModel> events = RxList<EventModel>([]);


Stream<List<EventModel>> eventStream(User? firebaseUser) =>
      FirebaseFirestore.instance
          .collection('events')
          .snapshots()
          .map((query) =>
              query.docs.map((item) => UserModel.fromMap(item)).toList());


@override
  void onReady() async {
    super.onReady();
    events.bindStream(
        eventStream(controller.firebaseUser)); // subscribe any change of events collection
  }

@override
  onClose() {
    super.onClose();
    events.close(); //close rxObject to stop stream
    
}

...
}

您可以在StreamBuilder.stream上使用文檔快照。 您可能希望將對 firebase 和 map 的調用抽象為您定義的實體。

  MyEntity fromSnapshot(DocumentSnapshot<Map<String, dynamic>> snap) {
    final data = snap.data()!;
    return MyEntity (
      id: snap.id,
      name: data['name'],
    );
  }

  Stream<MyEntity> streamEntity(String uid) {
    return firebaseCollection
        .doc(uid)
        .snapshots()
        .map((snapshot) => fromSnapshot(snapshot));
  }
  
  return StreamBuilder<MyEntity>(
    // you can use firebaseCollection.doc(uid).snapshots() directly
    stream: streamEntity(args.uid),
    builder: (context, snapshot) {
     if (snapshot.hasData) {
        // do something with snapshot.data
        return Scaffold(...);
      } else {
        // e.g. return progress indicator if there is no data
        return Center(child: CircularProgressIndicator());
      }
    },
  );

對於更復雜的數據模型,您可能需要查看簡單的 state 管理BLoC等模式。

暫無
暫無

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

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