现在,这也许是一种很好的做法,或者完全不行!

我试图抵制在StreamBuilder下放置更多build(BuildContext context),然后尝试使用initState()。由于无法正确使用Future / async / await,我遇到了麻烦。 String _leaseTenantName(第一个initState() Firestore.instance)将具有正确的值,但字符串_leaseUnitName_leaseUnitPropertyUid(第二个initState() Firestore.instance)通常将返回null。以下内部版本的StreamBuilder<PropertyDetails>会给出错误消息'Invalid document reference. Document references must have an even number of segments, but properties has 1, null)',但会继续尝试,并在_leaseUnitPropertyUid最终具有值时最终起作用。

我相信解决方案是以某种方式将两个initState() Firestore.instances包装在Future / async / await中,但无法解决此问题。有任何想法吗??还是应该使用更多嵌套的StreamBuilder

class _LeaseTileState extends State<LeaseTile> {
  String _leaseTenantName = '';
  String _leaseUnitPropertyUid = '';
  String _leaseUnitName = '';
  String _leasePropertyName = '';
  String _leasePropertyUnitName = '';

  @override
  void initState() {
    super.initState();
    Firestore.instance
        .collection("companies")
        .document(widget.leaseDetails.tenantUid)
        .snapshots()
        .listen((snapshot) {
      _leaseTenantName = snapshot.data['companyName'];
    });

    Firestore.instance
        .collection("units")
        .document(widget.leaseDetails.unitUid)
        .snapshots()
        .listen((snapshot) {
      _leaseUnitName = snapshot.data['unitName'];
      _leaseUnitPropertyUid = snapshot.data['propertyUid'];
    });
  }

  @override
  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);
    return StreamBuilder<PropertyDetails>(
        stream: DatabaseServices(propertyUid: _leaseUnitPropertyUid)
            .propertyByDocumentID,
        builder: (context, userCompany) {
          if (!userCompany.hasData) return Loading();
          _leasePropertyName = userCompany.data.propertyName;
          _leasePropertyUnitName = '$_leasePropertyName - $_leaseUnitName';
          return Card(

最佳答案

那是很大的不。

首先,使用多个StreamBuilder并没有错,StreamBuilder可以帮助您简化Streams的使用,因此您最终不会像在initState()中那样弄乱他们的订阅。

当您像在listen()上一样在snapshots()上调用initState()时,创建了一个订阅,该订阅应在dispose()上取消,但是您不取消它,因此您泄漏了内存,StreamBuilder会在您管理时将您保存在此处这个给你。

要记住的另一件事是,您在_leaseUnitPropertyUid上使用build(),但是您不检查_leaseUnitPropertyUid是否有效。仅在_leaseUnitPropertyUid Firebase snapshot()发出一个值并且可以在此之前调用Stream后才设置build()。同样,StreamBuilder将在这里保存您,您可以检查它是否发出了值。

另外,您还在代码上对Firebase.instance进行硬编码,这使得测试非常困难。看一看Dependency Injection并尝试将Firebase.instance注入(inject)到您的类中,例如Repository模式或类似的东西,以便您可以将Firebase.instace交换为测试Mock,并使您的代码更具可测试性。

关于firebase - 将两个Firestore.instances放置在initState()中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62096582/

10-11 09:12