如何在RxAndroid中停止订阅服务器?

时间:2016-11-24 09:28:35

标签: rx-java reactive-programming rx-android

我创建了一个像这样的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。仍然没有找到任何解决方案。

3 个答案:

答案 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()

来使用它来停止订阅