RxJava unsubscribeOn,递归调用不在正确的线程中

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RxJava unsubscribeOn,递归调用不在正确的线程中相关的知识,希望对你有一定的参考价值。

我在android应用程序中构建了一个无头webview,用于从网页中抓取URL。每次我检索URL时,我都可能需要使用此URL重做网页中的抓取。我正在使用RxJava同时处理这些操作,我正在使用flatMap函数进行递归调用。

问题是我需要在mainThread中处理WebView,所以我尝试添加.unsubscribeOn(AndroidSchedulers.mainThread()),但似乎它不起作用,并且dispose()中的HeadlessRequest方法在我称为observeOn(Schedulers.computation())的最后一个线程中被调用。在mainThread中执行dispose()方法应该更改什么?

这是我的代码:

HeadlessRequest

public class HeadlessRequest  implements Disposable {
    ...

    private class HeadlessWebView extends WebView {
        ...
         private void destroyWebView() {
            this.removeAllViews();
            this.clearCache(false);
            this.loadUrl("about:blank");
            this.onPause();
            this.removeAllViews();
            this.destroy();
            this.isDisposed = true;
        }
    }

    @Override
    public void dispose() {
        // This doesn't print the mainThread id
        Log.d(TAG, "Disposing on thread " + Thread.currentThread().getId());
        this.webView.destroyWebView();
        this.webView = null;
    }

    @Override
    public boolean isDisposed() {
        return (this.webView == null || this.webView.isDisposed);
    } 
}

NetworkUtils

public static Single<Document> downloadPageHeadless(final String url, final int delay, final Context context) {
        return Single.create((SingleEmitter<Document> emitter) -> {
            try {
                emitter.setDisposable(new HeadlessRequest(url, USER_AGENT, delay, context, emitter::onSuccess, emitter::onError));
            } catch (Exception e) {
                emitter.onError(e);
            }
        }).unsubscribeOn(AndroidSchedulers.mainThread()) //  It MUST be executed on the mainThread
                .subscribeOn(AndroidSchedulers.mainThread());
    }

Server服务

private static Single<String> resolveRecursive(String url, Context context) {
        Server server = getServerInstance(url, context);
        if (server == null) {
            return Single.error(new UnsupportedOperationException("Server for " + url + " not supported"));
        } else if (server.isVideo()) {
            return server.resolve(url, context);  // This method return a Single with observeOn(Schedulers.computation())
        } else {
            return server.resolve(url, context) 
                    .observeOn(Schedulers.computation())
                    .flatMap(resolvedUrl -> resolveRecursive(resolvedUrl, context));
        }
    }

 public static Single<String> resolveURL(String url, Context context) {
        return resolveRecursive(url, context)
                .observeOn(AndroidSchedulers.mainThread());
    }
答案

最后,我找到了另一种方法,在没有RxJava的情况下将webview部署在mainThread中。我使用了WebView的post方法。

private void destroyWebView() {
           this.post(() -> {
                this.removeAllViews();
                this.clearCache(false);
                this.loadUrl("about:blank");
                this.onPause();
                this.removeAllViews();
                this.destroy();
                this.isDisposed = true;
            });
        }

以上是关于RxJava unsubscribeOn,递归调用不在正确的线程中的主要内容,如果未能解决你的问题,请参考以下文章

Rxjava,改造和多次调用

如何使用 RXJava 调用的响应结果作为另一个 RXJava 函数中的 if 语句的条件?

RxJava defer操作符实现代码支持链式调用

RxJava编程思想1-(实现简易版Rxjava,如何基本功能和链式调用?)

android,rxjava中的PublishSubject没有调用onNext?

为啥 RxJava 的“订阅”方法会被多次调用?