RxJava отписаться с рекурсивным вызовом не в нужном потоке - PullRequest
0 голосов
/ 22 апреля 2019

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

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

Это мой код:

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

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 Ответ

0 голосов
/ 27 апреля 2019

В конце я нашел другой способ избавиться от веб-просмотра в 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;
            });
        }
...