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 函数中的 if 语句的条件?
RxJava编程思想1-(实现简易版Rxjava,如何基本功能和链式调用?)