-2

经过数小时的挣扎和浏览,我需要您的帮助。

我在一个实施了 Firestore 的颤振项目上。我在使用 Riverpod 的 mvvm 架构上。

我的firestore服务有这个代码:

CollectionReference getCollection(String collection) =>
      _firestore.collection(collection);

  getCurrentCustomer() {
    String uid = _auth.currentUser.uid;
    print('current customer id is : $uid');
    var customerStream = getCollection('customer')
        .doc(uid)
        .snapshots(includeMetadataChanges: true);
    print('customerStream is a $customerStream');
    return customerStream;
  }

我用这个提供者访问这个 FirestoreService :

final firestoreProvider = Provider<FirestoreService>((ref) {
  return FirestoreService(
    ref.read(authentificationServiceProvider),
  );
});

在我的 CustomerProfileViewModel 上,我得到了这个:

final customerProfileViewModelProvider =
    ChangeNotifierProvider<CustomerProfileViewModel>((ref) {
  return CustomerProfileViewModel(
    ref.read(authentificationServiceProvider),
    ref.read(navigationServiceProvider),
    ref.read(firestoreProvider),
  );
});

class CustomerProfileViewModel extends ChangeNotifier {
  final AuthentificationService _auth;
  final NavigationService _navigationService;
  final FirestoreService _firestore;

  CustomerProfileViewModel(
      this._auth, this._navigationService, this._firestore);


  getCurrentCustomerInfo() {
    Stream customerStream = _firestore.getCurrentCustomer();
    print('customer Stream sur le model est $customerStream');
    return customerStream;
  }

  updateCurrentUserInfo({String dataField, dataValue}) {
    _firestore.updateCurrentCustomerInfo(dataField, dataValue);
    notifyListeners();
  }
}

最后,在作为 ConsumerWidget 的 CustomerProfileView 中,我这样称呼我的模型:

var model = watch(customerProfileViewModelProvider);
var stream = model.getCurrentCustomerInfo();

并像这样设置了我的 StreamBuilder

StreamBuilder(
                stream: stream,
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> snapshot
    )

然后我得到这个错误:

I/flutter ( 2609): current customer id is : 9tZTfddurwQRsSuGnH7pkPvmvvF2
I/flutter ( 2609): customerStream is a Instance of '_MapStream<DocumentSnapshotPlatform, DocumentSnapshot>'
I/flutter ( 2609): customer Stream sur le model est Instance of '_MapStream<DocumentSnapshotPlatform, DocumentSnapshot>'
I/flutter ( 2609): stream view est Instance of '_MapStream<DocumentSnapshotPlatform, DocumentSnapshot>'

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following _TypeError was thrown building CustomerProfileView(dirty, dependencies: [UncontrolledProviderScope], state: _ConsumerState#b4319):
type '_MapStream<DocumentSnapshotPlatform, DocumentSnapshot>' is not a subtype of type 'Stream<QuerySnapshot>'

The relevant error-causing widget was: 
  CustomerProfileView file:///Users/Alex/AndroidStudioProjects/clickncollect/lib/ui/views/home/home_viewmodel.dart:35:16
When the exception was thrown, this was the stack: 
#0      CustomerProfileView.build (package:clickncollect_app/ui/views/customer/customer_profile/customer_profile_view.dart:40:25)
#1      _ConsumerState.build (package:flutter_riverpod/src/consumer.dart:300:35)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
...
════════════════════════════════════════════════════════════════════════════════════════════════

它使用 Future 进行所有相同的工作,使用 collection('customers').doc(uid).get() 查询并使用 FutureBuilder 构建它。

请帮助我,我从未见过这种 MapStream 类型,互联网也没有(经过数小时的搜索)。

谢谢阅读 !

4

2 回答 2

1
StreamBuilder(
    stream: stream,
    builder: (BuildContext context,
        AsyncSnapshot<DocumentSnapshot> snapshot //Your stream is of type <DocumentSnapshot> not <QuerySnapshot>
    // change it like this
)

为什么?getCurrentCostumer()在你返回的函数中

var customerStream = getCollection('customer').doc(uid)
  .snapshots(includeMetadataChanges: true);

如果您将 var 更改Stream<QuerySnapshot>为编辑器,则会警告您这不是流返回的类型,QuerySnapshot 是一个扩展 DocumentSnapshot 的类,而不是相反,当您使用类似where, limitAt,endsAt等查询时使用它,所以它是不是 Dart 误解了类型,但你正在将它转换为不同的类型

这是什么_MapStream<DocumentSnapshotPlatfom, DocumentSnapshot>而不是你问的 Stream?

快照使用函数map Stream.map()将每个元素转换为新的流事件,实现使用 this _MapStream<T, S>(this, convert) 所以它将事件 T 转换为 S,在这种情况下DocumentSnapshotPlatfom转换为DocumentSnapshot,这样你现在应该返回的流将是类型DocumentSnapshot

于 2020-11-27T17:16:44.733 回答
1

似乎不可能从 DocumentReference 请求一个流。所以我用 where 条件过滤了我的 CollectionReference 快照。我首先尝试过:

getCurrentCustomerInfo() {
    var uid = _auth.currentUser.uid;
  
    Stream customerStream = _firestore
        .getCollection('customers')
        .where('id', isEqualTo: uid)
        .snapshots();
    print('customer Stream on the model is ${customerStream}');
    return customerStream;
  }

但它没有用。然后我发现'id'问题在哪里,我发现了这个:

getCurrentCustomerInfo() {
    var uid = _auth.currentUser.uid;
    
    Stream customerStream = _firestore
        .getCollection('customers')
        .where(FieldPath.documentId, isEqualTo: uid)
        .snapshots();
    print('customer Stream on the model is ${customerStream}');
    return customerStream;
  }

然后在视图上你必须用这个来获取第一个元素

var customer = snapshot.data.docs.first.data();

您从流中获取快照中的数据。所以它更新了!

于 2020-11-27T15:40:59.427 回答