我创建了一个像这样的Observable:
public Observable<FileObjectModel> getAllFiles() {
return Observable.create(new Observable.OnSubscribe<FileObjectModel>() {
@Override
public void call(Subscriber<? super FileObjectModel> subscriber) {
//fileList is a huge list.
for(int i = 1 ; i < fileList.size(); i ++){
...
subscriber.onNext(fileItem);
}
}
});
}
然后订阅如下:
subscription = reposistory.getAllFiles()
.compose(scanInject())
.subscribe(...);
当用户点击按钮停止时,我想取消订阅,所以我打电话给
subscription.unsubscribe();
不幸的是,它并没有像预期的那样停止。文件项将继续发出。
请指出我的错误。
更新
我逐行调试,看到observable被卡在for
循环中。在这个循环中,我调用一个递归方法并将subscriber作为参数传递。该方法将浏览所有Android文件系统(从根文件夹开始)查找所有文件,然后逐个发出。 (我使用这种方式是因为整个系统上的文件数量非常大,不应该保存在任何静态列表中。)
由于我们被卡在for
循环中,因此订阅对象始终为null。仍然没有找到任何解决方案。
答案 0 :(得分:2)
首先,如果您打算使用Observable.create
,那么为了支持许多可能的下游运营商所需的背压,您需要追加.onBackpressureXXX
。如果有疑问,只需使用.onBackpressureBuffer
。
您无法取消订阅的原因是因为您的observable是同步的,因此在流完成之前不会设置subscription
!我建议一般避免使用这种模式,而是使用:
subscriber = ...;
reposistory.getAllFiles()
.compose(scanInject())
.subscribe(subscriber);
答案 1 :(得分:0)
我建议检查订阅者是否仍然订阅:
for(int i = 1 ; i < fileList.size(); i ++){
if (subscriber.isUnsubscribed()) {
return;
}
subscriber.onNext(fileItem);
}
这不应该是计算过载太多。
答案 2 :(得分:0)
无论如何我讨厌回答我的问题,但我已经找到了解决问题的根本原因和行动。
正如我在更新部分提到的那样,for
循环做了大量工作,它迭代了数千个项目。并且,处理器被卡在里面。
为了解决这个问题,我将不同的线程分配给observable,它运行异步,如下所示:
subscription = getAllObjects()
.map(this::doScan)
.observeOn(Schedulers.newThread())
.subscribeOn(Schedulers.newThread())
.subscribe(subscriber);
变量subscription
现在永远不会像以前一样null
,我们可以通过调用subscription.unsubscribe()