将 Firebase 当前用户(作为 Future)作为参数传递给 Stream 中的查询。有可能还是有其他方法?

Posted

技术标签:

【中文标题】将 Firebase 当前用户(作为 Future)作为参数传递给 Stream 中的查询。有可能还是有其他方法?【英文标题】:Passing Firebase current user (as Future) as a parameter to a query in a Stream. Is it possible or is there another way? 【发布时间】:2020-05-02 18:43:03 【问题描述】:

我有一个 Stream 从 Firebase 集合 QuerySnapShot 构建一个列表。如果我不将可变数据传递给查询('where' 语句),查询和流构建器工作得很好。但是,我要做的是将 FirebaseAuth.currentUser 作为过滤器传递给我的 Stream 的 where 子句。

我确信我对进行这 2 个单独的异步调用有些不理解。

基本上我需要获取当前经过身份验证的用户的 uid 并将其传递到我的流中的查询中。

我是 Flutter 的超级新手,并且正在快速获得我的印章。已经完全沉浸了大约一个星期。

class Booking 

  final DateTime startTime;
  final DateTime endTime;
  final String name;
  final String bookingId;
  final String truckID;

  Booking( this.bookingId, this.truckID, this.startTime, this.endTime, this.name );

// build the booking list from the QuerySnapShot
  List<Booking> _bookingListFromSnapshot(QuerySnapshot snapshot) 
    return snapshot.documents.map((doc) 
      return Booking(
          bookingId: doc.documentID ?? '',
          name: doc.data['name'] ?? '',
          startTime: doc.data['startTime'].toDate() ?? '',
          endTime: doc.data['endTime'].toDate() ?? '',
          truckID: doc.data['truckID']
      );
    ).toList();
  
//asynchronously get the uid of the currentuser from FirebaseAuth
  Future<String> inputData() async 
    final FirebaseUser _aUser = await FirebaseAuth.instance.currentUser();
    final String _uid = _aUser.uid.toString();
    return _uid;
  

这是我试图将当前用户传递到流中的地方

  //get user specific booking stream
  Stream<List<Booking>> get bookings 
    final _myUserId = inputData();  
    return bookingCollection
        .where("truckID", isEqualTo: _myUserId) //Instance of 'Future<String>'...needs to be the uid of the current user.
        .snapshots()
        .map(_bookingListFromSnapshot);
      
// the widget consuming the list
class _BookingListState extends State<BookingList> 
  @override
  Widget build(BuildContext context) 
    final bookings = Provider.of<List<Booking>>(context) ?? [];

    return ListView.builder(
      itemCount: bookings.length,
      itemBuilder: (context,index)
        return BookingTile(booking: bookings[index]);
      ,
    );
  

编辑以包含用于反馈的 Stream 使用情况(在按照建议将 Stream 包装在 Future 之后)

在我的 home.dart 文件中,我侦听 Stream&lt;List&lt;Booking&gt;&gt;&gt;,以便构建显示在该页面上的预订列表。在下一个块中,我现在收到一个错误,我无法将参数类型 Stream&lt;List&lt;Booking&gt;&gt; 分配给参数类型 Future&lt;Stream&lt;List&lt;Booking&gt;&gt;&gt;。编译器建议更改参数类型或将参数强制转换为&lt;Stream&lt;list&lt;Booking&gt;&gt;

完整的编译消息

lib/screens/home/home.dart:38:32: Error: The argument type 'Future<Stream<List<Booking>>>' can't be assigned to the parameter type 'Stream<List<Booking>>'.
 - 'Future' is from 'dart:async'.
 - 'Stream' is from 'dart:async'.
 - 'List' is from 'dart:core'.
 - 'Booking' is from 'package:models/booking.dart' ('lib/models/booking.dart').
Try changing the type of the parameter, or casting the argument to 'Stream<List<Booking>>'.
      value: DatabaseService().bookings,

home.dart

return StreamProvider<List<Booking>>.value(
      value: DatabaseService().bookings, 
      child: Scaffold( ... ) //Scaffold
      ); //StreamProvider.value

我尝试将参数value 或参数DatabaseService().value 更改为建议的类型...但我失败了:)

我根据反馈修改了预订获取器

  //get user specific booking stream
  Future<Stream<List<Booking>>> get bookings async 
    final _myUserId = await inputData();
    print(_myUserId);
    return bookingCollection
        .where("truckID", isEqualTo: _myUserId) //here is where I want to pass the currentUser
        .snapshots()
        .map(_bookingListFromSnapshot);
      

【问题讨论】:

您的函数 inputData() 是异步的,并返回一个 Future。这意味着您必须 await 它的结果才能将字符串从 Future 中取出,而您现在没有这样做。 感谢道格的回复。这是否意味着我需要以某种方式将该 Stream 写入另一个 async 函数(因为 await 表达式只能在异步函数中使用? 可能。我对 Dart 不是很熟悉,但是在 javascript 中,您只能在异步函数中等待。 【参考方案1】:

是的,您只能在异步函数中使用和等待期货。因此,首先按如下方式更改您的预订获取器。

//get user specific booking stream
  Future<Stream<List<Booking>>> get bookings 
    final _myUserId = await inputData();  
    return bookingCollection
        .where("truckID", isEqualTo: _myUserId) //Instance of 'Future<String>'...needs to be the uid of the current user.
        .snapshots()
        .map(_bookingListFromSnapshot);
      

因此,在您提供此流的地方,您需要提供 Future,然后才能从 Future 获取流。

【讨论】:

继续努力……对你的好建议做一点小改动;吸气剂也需要是async 显然现在我需要更改参数“值”类型,或者将参数DatabaseService().bookings 转换为Stream&lt;List&lt;Booking&gt;&gt; return StreamProvider&lt;List&lt;Booking&gt;&gt;.value( value: DatabaseService().bookings, .... ); //StreamProvider.value 我不清楚如何做到这一点。尝试了一些没有用的方法 感谢@dlohani ...我已经添加了修改后的 getter(供后代使用)和 Steam 侦听器,我在原始帖子中收到了最新错误。

以上是关于将 Firebase 当前用户(作为 Future)作为参数传递给 Stream 中的查询。有可能还是有其他方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中从 Firebase 获取当前用户 ID

如何在 Flutter 中基于 Future 结果构建 Stream?

将 Future<List> 从 Firestore 转换为 List<String> - Flutter Firebase [重复]

Android:从firebase获取当前日期和时间

在 Google SignIn 和 Firebase 中验证用户后,Flutter 将电子邮件用户参数传递到另一个页面

如何将用户当前用户详细信息插入Firebase中的另一个节点?