Flutter StreamSubscription不能暂停或停止。

3
在我的Flutter应用中,StreamSubscription无法暂停或取消。当我调用cancel()如果它在启动之前开始,它会停止。如果我在启动后调用cancel(),它将不会停止。我正在使用Firestore快照监听器。以下是我的代码。 我尝试了不同的方法,但仍然无法正常工作。问题在于Firestore listener在加载数据后没有停止。
    StreamSubscription<QuerySnapshot> streamSubscription;

    @override
    void initState() {
    super.initState();
    
        print("Creating a streamSubscription...");
        streamSubscription =Firestore.collection("name").document("d1").collection("d1")
            .snapshots().listen((data){
                //It will display items
            }, onDone: () { // Not excecuting
                print("Task Done");
            }, onError: (error) {
                print("Some Error");
        });
         streamSubscription.cancel(); //It will work but cancel stream before loading
    }

    @override
    void dispose() {
     streamSubscription.cancel(); //Not working
    super.dispose();
    }

stream.close() 应该改为 stream.cancel(),而 StreamSubscription 应该被称为 streamSubscriptionsubscription 而不是 stream,因为这很容易引起混淆,因为 Stream 是完全不同的东西。 - Günter Zöchbauer
在https://api.dartlang.org/stable/2.2.0/dart-async/StreamSubscription-class.html中没有`close()`,所以它不起作用并不奇怪。如果您收到错误消息,请将该错误消息与您的问题一起发布。 - Günter Zöchbauer
我已经编辑了我的问题。我正在使用'cancel()'而不是'close'。对于错误的发生,我很抱歉。 - Joe
@GünterZöchbauer 当我跳转到另一个页面时,监听器没有停止。它正在执行新页面并中断其他监听器。我在dispose()中添加了cancel,但它并没有取消执行新页面。 - Joe
显示剩余2条评论
3个回答

4

2

你没有将订阅分配给正确的变量。

注:Original Answer翻译成“最初的回答”

StreamSubscription<QuerySnapshot> subscription;

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

    print("Creating a streamSubscription...");
    subscription=Firestore.collection("name").document("d1").collection("d1")
        .snapshots().listen((data){
            //It will display items
        }, onDone: () { // Not excecuting
            print("Task Done");
        }, onError: (error) {
            print("Some Error");
    });


     subscription.cancel(); //It will work but cancel stream before loading



}

@override
void dispose() {
 subscription.cancel(); //Not working
super.dispose();
}

1
这是我问题中的错误。我修改了我的问题。我将其分配给正确的变量。请再次检查问题并检查您的答案。 - Joe
@Joe 你尝试过检查dispose函数是否被调用了吗?在dispose函数内打印一些内容,看看它是否被调用了。 - dshukertjr
1
我已经尝试在 dispose() 中处理,我的 dispose() 能够正常工作,但是无法取消监听。在调用新屏幕之前,我也调用了 Navigator.push(context,MaterialPageRoute(builder: (context) => SecondScreen())); - Joe
有人能告诉我为什么这里 onDone 没有执行吗? - Piyush Jain

1
我曾经遇到过同样的问题,后来发现流似乎会在取消之前继续监听一段时间,但是如果你进行调试,你会发现在调用 dispose 后它会停止监听。因此,Gunter's 的解决方案很好,因为如果挂载为 false,也就是说你的页面不存在了,你可以防止回调函数被调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接