白驹过隙,这篇文章距今已有一年以上的历史。技术发展日新月异,文中的观点或代码很可能过时或失效,请自行甄别:)

问题

在使用Flutter的Stream来实现一个打印机队列系统的时候, 发现了这么一个诡异的问题. 先简单说下代码. 其实很简单,就是当打印机状态不可用时, 我会调用StreamSubscripton.pause()来暂停队列的消费, 当打印机变为可用后, 调用StreamSubscription.resume(). 但是很诡异的是在resume后, 再想Stream里面投递消息后, Subscription仍然没有任何消息进来.

原因

找了很久, 也单独写了一个demo, 发现demo并没有问题, 直到我发现我代码里面是这样写的.


pause() {
...
   streamSub?.pause();
...
}

resume() {
...
    steramSub?.resume();
...
}

问题就出在这里, 每次在pause和resume的时候,并没有判断该订阅是否有暂停. 由于会轮询打印机状态并切周期性调用上述的对应代码, 这就导致被多次触发暂停和恢复. 而文档上有这么一句: If the subscription is paused more than once, an equal number of resumes must be performed to resume the stream. 意思是说, 你调用了多少次暂停, 要恢复, 也得调用对应次数的恢复才行.

解决办法

所以, 代码改为这样就好了

pause() {
    ...
    if( streamSub != null && !streamSub.isPaused() ) {
       streamSub?.pause();
    }
    ...
}

resume() {
    ...
    if( streamSub != null && streamSub.isPaused() ) {
       streamSub.resume();
    }
    ...
}

最后

多看文档, 多看手册能少趟很多坑