从正确的线程调用RxJava2可取消/一次性

时间:2017-10-18 22:18:23

标签: android kotlin rx-java rx-java2

我正在实施一个可观察到的Resource

的线条

问题是这个资源真的不喜欢从它创建的不同线程关闭(它会杀死一只小狗并在发生这种情况时抛出异常)。

当我处理订阅时,从Cancellable线程调用资源Disposable / main,而Schedulers.io()订阅了observable。

这是Kotlin代码:

fun lines(): Observable<String> =
        Observable.create { emitter ->
            val resource = NetworkResource()
            emitter.setCancellable {
                resource.close() // <-- main thread :(
            }
            try {
                while (!emitter.isDisposed)
                    emitter.onNext(resource.readLine()) // <-- blocked here!
            } catch (ioe: IOException) {
                emitter.tryOnError(ioe) // <-- this also triggers the cancellable
            }
        }

val disposable = lines()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { Log.i(TAG, "Line: $it" }

disposable.dispose() // <-- main thread :)

问题:是否可以从正确的*主题中调用Cancellable,同时考虑到resource.readLine()上的订阅主题已被屏蔽?

*正确的线程意味着subscribeOn(Schedures.io())中的那个。

编辑:我担心这个问题没有正确的答案,除非resource.close()是线程安全的,或者resource.dataReady上的某种轮询已经实现,以便线程未被阻止。

3 个答案:

答案 0 :(得分:2)

Schedulers.io()管理线程池,因此它可能会也可能不会使用相同的线程来处置您的资源。您必须使用自定义调度程序和unsubscribeOn()运算符,以确保在同一个线程上订阅和取消订阅Observable。类似的东西:

Scheduler customScheduler = Schedulers.from(Executors.newSingleThreadExecutor());

val disposable = lines()
        .unsubscribeOn(customScheduler)
        .subscribeOn(customScheduler)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { Log.i(TAG, "Line: $it" }

答案 1 :(得分:1)

如果您不介意稍微延迟拨打NetworkResource#close,为什么不呢

    fun lines(): Observable<String> =
            Observable.create { emitter ->
                val resource = NetworkResource()
                try {
                    while (!emitter.isDisposed) {
                        emitter.onNext(resource.readLine())
                    }
                    resource.close()
                } catch (ioe: IOException) {
                    emitter.tryOnError(ioe)
                }
            }

但是仍有一个问题:如果IOException,任何人都不会打电话给NetworkResource#close(我也认为这个问题的例子也是如此)。

尝试解决此问题:

    fun lines(): Observable<String> =
            Observable.create { emitter ->
                val resource = NetworkResource()
                try {
                    while (!emitter.isDisposed) {
                        emitter.onNext(resource.readLine()) 
                    }
                } catch (ioe: IOException) {
                    emitter.tryOnError(ioe)
                } finally {
                    resource.close() // try-catch here, too?
                }
            }

或使用&#34; Kotlin-Try-With-Resources&#34;函数use

    fun lines(): Observable<String> =
            Observable.create { emitter ->
                NetworkResource().use { resource ->
                    try {
                        while (!emitter.isDisposed) {
                            emitter.onNext(resource.readLine())
                        }
                    } catch (ioe: IOException) {
                        emitter.tryOnError(ioe)
                    }
                }
            }

我希望,这有帮助。祝你周末愉快。

答案 2 :(得分:0)

如何选择其他途径?

a)通过制作NetworkResource线程安全(如果您控制源代码)

b)通过NetworkResource与&#34;代理&#34; 包装在一起?使用&#34; agent&#34;我的意思是一个内部使用专用线程的代理,它与NetworkResource进行所有交互(构造,readLine,close,...)

相关问题