RxJava отписался от рекурсивного вызова не в правильном потоке

#android #android-webview #rx-java2 #headless-browser #unsubscribe

#Android #android-webview #rx-java2 #безголовый браузер #отписаться

Вопрос:

Я создал безголовый веб-просмотр в приложении Android для удаления URL-адреса с веб-страницы. Каждый раз, когда я получаю URL-адрес, мне может потребоваться повторить очистку веб-страницы с этим URL-адресом. Я использую RxJava для одновременной обработки этих операций, и я использую flatMap функцию для выполнения рекурсивного вызова.

Проблема в том, что мне нужно удалить WebView в MainThread, поэтому я попытался добавить .unsubscribeOn(AndroidSchedulers.mainThread()) , но, похоже, это не работает, и dispose() метод in HeadlessRequest вызывается в последнем вызванном мной потоке observeOn(Schedulers.computation()) . Что я должен изменить, чтобы выполнить dispose() метод в MainThread?

Это мой код:

Запрос без заголовка

 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());
    }
  

ServerService

 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());
    }
  

Ответ №1:

В конце я нашел другой способ удаления webview в MainThread без RxJava. Я использовал post метод WebView.

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