Flutter - StreamProvider - 向 Firebase 发送重复出现的 XHR 请求

Posted

技术标签:

【中文标题】Flutter - StreamProvider - 向 Firebase 发送重复出现的 XHR 请求【英文标题】:Flutter - StreamProvider - Sending reoccuring XHR Requests to Firebase 【发布时间】:2020-08-24 16:02:59 【问题描述】:

我注意到我的读取请求显着增加,因为我使用StreamProvider 添加了一个新流,我设法通过删除流并且没有重复请求来确认这一点。但我似乎无法追查为什么它会重复。

注意:代码功能正常,只是这些读取请求已经过火了。

串流

//get list of all open enquiries
  Stream<List<EnquiryData>> get centreDashboardOpenEnquiries 
    return centresCollection.document(centreID).collection('enquiries').where('enquiryStatus', whereIn: ['New', 'Contacted', 'Tour Scheduled', 'Tour Completed']).snapshots().map(_enquiryList);
  

  //Map QuerySnapshot to List of EnquiryData
  List<EnquiryData> _enquiryList(QuerySnapshot enquiry)
    return enquiry.documents.map((doc) 
      return EnquiryData(
        enquiryID: doc.data['enquiryID'].toString(),
        parentFirstName: doc.data['firstName'],
        parentLastName: doc.data['lastName'],
        parentPhoneNumber: doc.data['phoneNumber'],
        parentEmail: doc.data['email'],
        parentAddress: doc.data['address'],
        methodOfEnquiry: doc.data['methodOfEnquiry'],
        hearAboutUs: doc.data['hearAboutUs'],
        specificHearAboutUs: doc.data['specificHearAboutUs'],
        impressionOfCentre: doc.data['firstImpression'],
        enquiryStatus: doc.data['enquiryStatus'],
        created: doc.data['created'],
        lastUpdated: doc.data['lastUpdated'],
      );
    ).toList();
  

使用 CurrentOpenDataTable 子级调用流

child: StreamProvider<List<EnquiryData>>.value(
    value: EnquiryDatabaseService(centreID: widget.centreData.centreID).centreDashboardOpenEnquiries,
    child: CurrentOpenDataTable(),
),

CurrentOpenDataTable()

class CurrentOpenDataTable extends StatefulWidget 
  @override
  _CurrentOpenDataTableState createState() => _CurrentOpenDataTableState();


class _CurrentOpenDataTableState extends State<CurrentOpenDataTable> 
  @override
  Widget build(BuildContext context) 
    final enquiryData = Provider.of<List<EnquiryData>>(context) ?? [];
    return DataTable(
      showCheckboxColumn: false,
      sortColumnIndex: 1,
      sortAscending: true,
      columns: [
        DataColumn(
          label: Text('Date'),
        ),
        DataColumn(
          label: Text('Name'),
          //numeric: true,
        ),
        DataColumn(
          label: Text('Status'),
        ),
      ],
      rows: _enquiryRow(context, enquiryData),
    );
  


_dateFormat(DateTime dateTime) 
  String formattedDate = DateFormat('dd/MM/yyyy').format(dateTime);
  return formattedDate;


_enquiryRow(BuildContext context, List<EnquiryData> enquiryData) 
  List<DataRow> listOfDataRows = List.generate(
      enquiryData.length,
      (index) => DataRow(
              cells: [
                DataCell(Text(_dateFormat(DateTime.fromMillisecondsSinceEpoch(
                    enquiryData[index].created)))),
                DataCell(Text(enquiryData[index].parentFirstName +
                    ' ' +
                    enquiryData[index].parentLastName)),
                DataCell(Text(enquiryData[index].enquiryStatus)),
              ],
              onSelectChanged: (bool selected) 
                if (selected) 
                  showEnquiryDialog(context, enquiryData[index]);
                
              ));
  return listOfDataRows;

【问题讨论】:

【参考方案1】:

包含StreamProvider 的小部件(我们称之为MyWidget)不断被重建。

您不应该在StreamProvider&lt;List&lt;EnquiryData&gt;&gt;.value 中创建EnquiryDatabaseService,而是在initState 中获取流。

例子

class _MyWidgetState extends State<MyWidget> 
  Stream<List<EnquiryData>> _stream;

  @override
  initState() 
    _stream = EnquiryDatabaseService(centreID: widget.centreData.centreID). centreDashboardOpenEnquiries;
  

  // ... in build
  StreamProvider.value(
    value: _stream,
    child: Container(/* ... */),
  ),

或者不要使用.value 构造函数。

StreamProvider(
  create: (_) => EnquiryDatabaseService(centreID: widget.centreData.centreID). centreDashboardOpenEnquiries,
  child: Container(/* ... */),
),

阅读更多关于do's and don'ts here 更多参考在这里 - How to deal with unwanted widget build?

【讨论】:

以上是关于Flutter - StreamProvider - 向 Firebase 发送重复出现的 XHR 请求的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:如何处理使用 StreamProvider、FireStore 和使用 Drawer

Flutter Riverpod:使用 StreamProvider 返回 2 个流

Flutter:StreamProvider 的奇怪行为,使用不完整数据重建的小部件

Flutter Provider,当他的参数改变时更新 StreamProvider

如何在 Flutter (Dart) 中通过新路由获取子级 StreamProvider 数据

Flutter:带有 onAuthStateChanged 的​​ StreamProvider<FirebaseUser> 始终返回 null 作为第一个值