Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Firebase 云Firestore不断重新下载文档-颤振_Firebase_Flutter_Google Cloud Firestore - Fatal编程技术网

Firebase 云Firestore不断重新下载文档-颤振

Firebase 云Firestore不断重新下载文档-颤振,firebase,flutter,google-cloud-firestore,Firebase,Flutter,Google Cloud Firestore,这发生在我的主应用程序中 和 我使用给定的代码实验室复制它: import'包:cloud_firestore/cloud_firestore.dart'; 进口“包装:颤振/材料.省道”; void main()=>runApp(MyApp()); 类MyApp扩展了无状态小部件{ @凌驾 小部件构建(构建上下文){ 返回材料PP( 标题:“婴儿名字”, 主页:MyHomePage(), ); } } 类MyHomePage扩展StatefulWidget{ @凌驾 _MyHomePageS

这发生在我的主应用程序中 和 我使用给定的代码实验室复制它:

import'包:cloud_firestore/cloud_firestore.dart';
进口“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“婴儿名字”,
主页:MyHomePage(),
);
}
}
类MyHomePage扩展StatefulWidget{
@凌驾
_MyHomePageState createState(){
返回_MyHomePageState();
}
}
类_MyHomePageState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(标题:文本(“婴儿名字投票”),
正文:_buildBody(上下文),
);
}
Widget\u buildBody(BuildContext上下文){
返回流生成器(
流:Firestore.instance.collection('baby').snapshots(),
生成器:(上下文,快照){
如果(!snapshot.hasData)返回LinearProgressIndicator();
返回构建列表(上下文、快照、数据、文档);
},
);
}
小部件构建列表(构建上下文上下文,列表快照){
返回列表视图(
填充:仅限常量边集(顶部:20.0),
子项:snapshot.map((数据)=>\u buildListItem(上下文,数据)).toList(),
);
}
小部件_buildListItem(BuildContext上下文,DocumentSnapshot数据){
最终记录=记录。从快照(数据);
返回填充(
key:ValueKey(记录名称),
填充:常量边集。对称(水平:16.0,垂直:8.0),
子:容器(
装饰:盒子装饰(
边框:边框。全部(颜色:颜色。灰色),
边界半径:边界半径。圆形(5.0),
),
孩子:ListTile(
标题:文本(记录名称),
尾随:文本(record.vows.toString()),
onTap:()=>打印(记录),
),
),
);
}
}
课堂记录{
最后的字符串名;
最后整数票;
最终文件参考;
Record.fromMap(映射映射,{this.reference})
:assert(映射['name']!=null),
断言(映射['voates']!=null),
name=map['name'],
投票=地图[‘投票’];
Record.fromSnapshot(文档快照快照)
:this.fromMap(snapshot.data,reference:snapshot.reference);
@凌驾
字符串toString()=>“记录”;
}
我使用的唯一插件是cloud\u firestore 0.9.5+2。请耐心等待这个测试过程。你不会马上看到这个问题。首先运行应用程序,设置此项目。您可以按照给定代码实验室中的说明进行操作。在前端和后端完成所有设置后(在firstore上创建文档)。去吃午饭,吃晚饭,玩电子游戏或者和朋友出去玩。1小时后回来。运行该应用程序,您将因读取新内容而产生费用。再做一次,回来一个小时,它就会再次发生

如何在现实生活中复制它: 通过codelabs提供的给定代码启动此应用程序。运行它,如果您在firestore中存储了4个文档,那么它将导致4个文档读取

重新启动它。免费阅读。太好了,它工作了!但是不,它真的没有

我第二天醒来,打开应用程序,我收费4次阅读。好吧,也许发生了什么奇迹。我立即重新启动它,不会产生任何费用(太好了!)1小时后,我启动应用程序,并收取4次读取费用,以显示完全相同的4个未更改的文档。

问题是,在应用程序启动时。它似乎正在从查询快照下载文档。文件未作任何更改。此流生成器以前已运行过多次

脱机模式(飞机模式),缓存的数据显示无问题。

例如,在我的主应用程序中,我有一个photoUrl,在fresh App start上,您可以看到它从firestore加载(这意味着作为新文档下载,因此会产生读取费用)。我重新启动我的主应用程序,不收费,照片也不刷新(太好了!)。1小时后,我启动应用程序,并为我检索的每个文档收费(所有文档均未更改)

云firestore就是这样运作的吗?
从我所读到的内容来看,它的行为不应该是这样的:(

除了构建小部件树之外,您不应该在
build()
中执行实际工作

而不是像这样的代码

stream: Firestore.instance.collection('baby').snapshots(),
你应该使用

Stream<Snapshot> babyStream;
@override
void initState() {
  super.initState();
  babyStream = Firestore.instance.collection('baby').snapshots();
}

Widget _buildBody(BuildContext context) {
 return StreamBuilder<QuerySnapshot>(
   stream: babyStream,
   builder: (context, snapshot) {
     if (!snapshot.hasData) return LinearProgressIndicator();

     return _buildList(context, snapshot.data.documents);
   },
 );
}
streambabystream;
@凌驾
void initState(){
super.initState();
babyStream=Firestore.instance.collection('baby').snapshots();
}
Widget\u buildBody(BuildContext上下文){
返回流生成器(
溪流:babyStream,
生成器:(上下文,快照){
如果(!snapshot.hasData)返回LinearProgressIndicator();
返回构建列表(上下文、快照、数据、文档);
},
);
}
FutureBuilder文档没有明确提到它,但它是相同的

未来必须提前获得,例如在 State.initState、State.didUpdateConfig或 State.didChangeDependencies。在 构造时调用State.build或StatelessWidget.build方法 FutureBuilder。如果未来与 FutureBuilder,然后每次重建FutureBuilder的父对象时, 异步任务将重新启动

我想我正面临着这个问题。在30分钟内(我测试了很多次),我可以启动我的应用程序,并且不会计算读取次数。在等待(关闭应用程序>)30~35分钟后,我再次启动应用程序,并对查询中的每个文档收取费用

现在,如果我让一个侦听器保持打开状态(而不是关闭其订阅),那么应该避免这种情况,而是下载被修改的文档

我试过这个:

  List<DocumentSnapshot> nameDocs = [];
  StreamSubscription nameSub;
  @override
  void initState() {
    super.initState();
    nameSub = Firestore.instance.collection('baby').snapshots().listen((data) {
      print('listener Fired at line 39 main.dart');
      data.documentChanges.forEach((x) {
        print('${x.type} this is the type line 40');
        if (x.type == DocumentChangeType.modified) {
          print('modified');
          nameDocs.removeAt(x.oldIndex);
          setState(() {
            nameDocs.add(x.document);
          });
        }
        if (x.type == DocumentChangeType.added) {
          print('added');
          setState(() {
            nameDocs.add(x.document);
          });
        }
        if (x.type == DocumentChangeType.removed) {
          print('removed');
          setState(() {
            nameDocs.removeAt(x.oldIndex);
          });
        }
        print(x.document.data['name']);
      });
    });
  }
List nameDocs=[];
流订阅名称订阅;
@凌驾
void initState(){
super.initState();
nameSub=Firestore.instance.collection('baby').snapshots().listen((数据){
打印('侦听器在第39行激发
Also, if the listener is disconnected for more than 30 minutes (for example, if the user goes offline), you will be charged for reads as if you had issued a brand-new query.
  List<DocumentSnapshot> nameDocs = [];
  StreamSubscription nameSub;
  @override
  void initState() {
    super.initState();
    nameSub = Firestore.instance.collection('baby').snapshots().listen((data) {
      print('listener Fired at line 39 main.dart');
      data.documentChanges.forEach((x) {
        print('${x.type} this is the type line 40');
        if (x.type == DocumentChangeType.modified) {
          print('modified');
          nameDocs.removeAt(x.oldIndex);
          setState(() {
            nameDocs.add(x.document);
          });
        }
        if (x.type == DocumentChangeType.added) {
          print('added');
          setState(() {
            nameDocs.add(x.document);
          });
        }
        if (x.type == DocumentChangeType.removed) {
          print('removed');
          setState(() {
            nameDocs.removeAt(x.oldIndex);
          });
        }
        print(x.document.data['name']);
      });
    });
  }