Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.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
Dart StreamBuilder限制_Dart_Flutter_Future_Stream Builder_Flutter Navigation - Fatal编程技术网

Dart StreamBuilder限制

Dart StreamBuilder限制,dart,flutter,future,stream-builder,flutter-navigation,Dart,Flutter,Future,Stream Builder,Flutter Navigation,StreamBuilder在获得新事件时重新生成。这会导致例如导航(Navigator.push)出现问题,因为如果在导航时接收到新事件,则此触发器将重新生成。因为在小部件树仍在构建时尝试导航,这将抛出 应根据需要避免此问题 建议的解决方法基本上是从中获取流。 也: 和 但这意味着,如果还想从列表中的卡片提供导航,则不能让StreamBuilder构建列表不断更新。例如,在卡片onPressed()中 所以要刷新数据,必须使用pull来刷新 谁有更好的解决办法? 或者,Flatter团队是否正

StreamBuilder
在获得新事件时重新生成。这会导致例如导航(
Navigator.push
)出现问题,因为如果在导航时接收到新事件,则此触发器将重新生成。因为在小部件树仍在构建时尝试导航,这将抛出

应根据需要避免此问题

建议的解决方法基本上是从中获取流。 也: 和

但这意味着,如果还想从列表中的卡片提供导航,则不能让StreamBuilder构建列表不断更新。例如,在卡片
onPressed()

所以要刷新数据,必须使用pull来刷新

谁有更好的解决办法? 或者,Flatter团队是否正在解决此限制,例如,如果用户点击卡,是否允许防止重建

更新:

TL;DR是更新数据的唯一方法,因为必须缓存StreamBuilder中的流,以防止每次收到新事件时重新生成流

更新2:

我已尝试实现缓存数据,但我的代码不起作用:

Stream<QuerySnapshot> infoSnapshot;

fetchSnapshot()  {
  Stream<QuerySnapshot> infoSnapshot = Firestore.instance.collection(‘info’).where(‘available’, isEqualTo: true).snapshots();
  return infoSnapshot;
}


  @override
  void initState() {
    super.initState();
  fetchSnapshot();
  }
更新3:

我已尝试使用
StreamController
,但无法实现正确的:

Stream<QuerySnapshot> infoStream;
StreamController<QuerySnapshot> infoStreamController = StreamController<QuerySnapshot>();

  @override
  void initState() {
    super.initState();

  infoStream = Firestore.instance.collection(‘info’).where(‘available’, isEqualTo: true).snapshots();
  infoStreamController.addStream(infoStream);
  }
更新4:

建议使用
\u localStreamController
给出错误:

StreamController<QuerySnapshot> _localStreamController = StreamController<QuerySnapshot>();

  @override
  void initState() {
    super.initState();

Firestore.instance.collection(‘info’).snapshots().listen((QuerySnapshot querySnapshot) {

//      if(userAdded == null) {
        _localStreamController.add(querySnapshot);
//      }

    });
...
child: StreamBuilder(
stream: _localStreamController.stream,
builder: (context, snapshot) {
StreamController\u localStreamController=StreamController();
@凌驾
void initState(){
super.initState();
Firestore.instance.collection('info').snapshot().listen((QuerySnapshot QuerySnapshot){
//if(userAdded==null){
_localStreamController.add(querySnapshot);
//      }
});
...
孩子:StreamBuilder(
流:_localStreamController.stream,
生成器:(上下文,快照){
对null调用了getter“stream”

已对调用方法“add” 空


根据您上面的评论,实际问题似乎是,在您使用流导航离开视图后,它会崩溃。您必须:

  • 当您离开时取消流控制器,使其不再侦听任何事件
  • 或者只是在导航后不通过流发出任何新值。在返回视图之前在流上添加暂停
更新:添加带有伪示例的代码

class Widget {
  // Your local stream 
  Stream<String> _localStream;
  // Value to indicate if you have navigated away
  bool hasNavigated = false;
  ...
  void init() {
    // subscribe to the firebase stream
    firebaseStream...listen((value){
      // If this value is still false then emit the same value to the localStream
      if(!hasNavigated) {
        _localStream.add(value);
      }
    });
  }

  Widget build() {
    return StreamBuilder(
      // subscribe to the local stream NOT the firebase stream
      stream: _localStream,
      // handle the same way as you were before
      builder: (context, snapshot) {
         return YourWidgets();
      }
    );
  }
}
类小部件{
//您的本地流
Stream\u localStream;
//值以指示是否已导航离开
bool hasNavigated=false;
...
void init(){
//订阅firebase流
firebaseStream…侦听((值){
//如果此值仍然为false,则向localStream发出相同的值
如果(!已导航){
_localStream.add(value);
}
});
}
小部件构建(){
返回流生成器(
//订阅本地流,而不是firebase流
流:_localStream,
//和以前一样处理
生成器:(上下文,快照){
返回您的widgets();
}
);
}
}

尝试将所有内容分解为小部件

即使完全关闭应用程序,运行查询也应该缓存它(我相信只在完全关闭时缓存它最多30分钟,但如果您没有internet连接,您仍然可以从Firestore访问以前缓存的查询

试着这样做:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Please work')),
      body: _buildStream(context),
    );
  }

  Widget _buildStream(BuildContext context) {
     return StreamBuilder(
      stream: yourFireStoreStream,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return LinearProgressIndicator();

        return _buildAnotherwidget(context, snapshot.data.documents);
      },
    );
  }
  Widget _buildAnotherwidget(Buildcontext context, List<DocumentSnapshot> snaps){
    return ListView.Builder(
      itemCount: snaps.length,
      itemBuilder:(context, index) {
      ..dostuff here...display your cards etc..or build another widget to display cards
         }
     );
 }
@覆盖
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(标题:文本(“请工作”),
正文:_buildStream(上下文),
);
}
Widget\u buildStream(BuildContext上下文){
返回流生成器(
stream:yourFireStoreStream,
生成器:(上下文,快照){
如果(!snapshot.hasData)返回LinearProgressIndicator();
return\u buildAnotherwidget(上下文、快照、数据、文档);
},
);
}
Widget\u buildAnotherwidget(Buildcontext上下文,列表快照){
返回ListView.Builder(
itemCount:snaps.length,
itemBuilder:(上下文,索引){
…在这里显示您的卡片等…或构建另一个小部件来显示卡片
}
);
}
专注于分解更多的小部件。最高部分应该有streambuilder和流。然后深入到更多的小部件。 streambuilder将自动侦听并订阅给定流

当streambuilder更新时,它将更新较低的小部件

现在这样,当您点击较低窗口小部件中的卡片进行导航时,它不应该影响最高窗口小部件,因为它只会影响UI

我们将streambuilder放在它自己的顶级小部件中

我希望我说得有道理:(


我在没有测试的情况下编写了代码,但我相信你可以让它正常工作

你在寻求什么帮助?实际问题是什么?@FilledStacks问题:拉刷新是实现此功能的唯一方法吗?你到底想实现什么?你的目标是什么?你想在哪里和什么时候使用
导航状态#push()
method?@pskink需要调用
Navigator。按下
onPressed()中的
在卡片列表中,其中
StreamBuilder
buildbyreturn
ListView.builder
@HeavenOSK我添加了代码我的流来自Firestore,所以我想你的答案不是possible@FlutterFirebase这绝对是可能的。在您的状态视图中本地订阅长笛流,转换并发出通过l的值您所在状态的本地流。使用widget builder中的本地流,而不是firestore状态。当您导航离开时,取消对您设置的本地流的订阅。然后您将不会获得任何更多值。感谢您的回复!我正在尝试实现您的缓存,但无法正常工作。我有更新问题code@FlutterFirebase那不是它不是一个缓存实现,而且,您不需要缓存任何东西。您只需在使用firebase流原样之间添加一个步骤即可:/n现在没有时间键入代码。我稍后将回到这一点,并编写伪代码以提供帮助
class Widget {
  // Your local stream 
  Stream<String> _localStream;
  // Value to indicate if you have navigated away
  bool hasNavigated = false;
  ...
  void init() {
    // subscribe to the firebase stream
    firebaseStream...listen((value){
      // If this value is still false then emit the same value to the localStream
      if(!hasNavigated) {
        _localStream.add(value);
      }
    });
  }

  Widget build() {
    return StreamBuilder(
      // subscribe to the local stream NOT the firebase stream
      stream: _localStream,
      // handle the same way as you were before
      builder: (context, snapshot) {
         return YourWidgets();
      }
    );
  }
}
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Please work')),
      body: _buildStream(context),
    );
  }

  Widget _buildStream(BuildContext context) {
     return StreamBuilder(
      stream: yourFireStoreStream,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return LinearProgressIndicator();

        return _buildAnotherwidget(context, snapshot.data.documents);
      },
    );
  }
  Widget _buildAnotherwidget(Buildcontext context, List<DocumentSnapshot> snaps){
    return ListView.Builder(
      itemCount: snaps.length,
      itemBuilder:(context, index) {
      ..dostuff here...display your cards etc..or build another widget to display cards
         }
     );
 }