首页 > 解决方案 > 在 initState() 中放置两个 Firestore.instances

问题描述

现在这可能是一个很好的做法,或者完全不!

我试图抵制在StreamBuilder下面放置更多(s)build(BuildContext context)并尝试使用initState()Future由于没有正确使用// async,我遇到了麻烦await。( String _leaseTenantNamefirst initState() Firestore.instance) 将具有正确的值,但 Strings _leaseUnitName& _leaseUnitPropertyUid(second 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//中asyncawait但无法找到一种方法来做到这一点。有任何想法吗??还是我应该使用更多的嵌套StreamBuilders?

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(

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


这是一个很大的不。

首先,使用 multiple 并没有错StreamBuilderStreamBuilder帮助您简化使用,Streams这样您就不会像在initState().

当您像在listen()snapshots()一样调用时initState(),您创建了一个订阅,该订阅应该在 上取消dispose(),但您没有取消它,因此您正在那里泄漏内存,aStreamBuilder会在它为您管理时将您保存在这里。

要记住的另一件事是您正在使用_leaseUnitPropertyUidon build(),但您不检查是否_leaseUnitPropertyUid有效。_leaseUnitPropertyUid只会在Firebase snapshot() Stream发出一个值之后设置,并且build()可以在此之前调用。再次,StreamBuilder将您保存在这里,并且您可以检查它是否已发出值。

此外,您正在Firebase.instance对代码进行硬编码,这使得测试变得非常困难。查看依赖注入并尝试将其注入Firebase.instance到您的类中,例如存储库模式或类似的东西,这样您就可以将其替换Firebase.instace为测试Mock并使您的代码更具可测试性。


推荐阅读