Как выполнять операции в другом потоке, а затем уведомлять основной поток в rxandroid?

Я в значительной степени понимаю концепцию подписки (любой код ниже subscribeOn будет выполняться в этом конкретном потоке) и наблюдаю (то же самое с subscribeOn) в rxandroid/rxjava.

Что я хочу, так это выполнить длинную операцию ввода-вывода в фоновом потоке, а затем уведомить основной поток, если операции завершены. Для этого я думаю иметь flatmap, который подписан в Schedulers.io(), а затем наблюдать subscribe в AndroidSchedulers.mainThread(), что-то вроде этого:

Observable.just(1)
          .subscribeOn(Schedulers.io())
          .flatMap(o -> {
            longIO();
            return null;})
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(//i want to notify user here);

Это фактически выполняет longIO() в другом потоке, таким образом, не блокируя основной поток, моя проблема в том, что это не уведомляет основной поток о завершении longIO(), обратите внимание, что Android не позволяет уведомлять пользователя, создавая Toast или AlertDialog, если не в основном потоке. Код не проходит через subscribe

Примечание: я использовал just(1), хотя я не использую целое число 1, потому что я хочу, чтобы метод внутри flatMap выполнялся. Если бы я использовал empty, он не прошел бы через flatMap


person hehe    schedule 25.08.2016    source источник
comment
stackoverflow.com /questions/34272955/ Перейдите по этой ссылке   -  person Vijayaramanan    schedule 26.08.2016
comment
Я проверю позже, если это решит мою проблему.   -  person hehe    schedule 26.08.2016


Ответы (2)


Тип возвращаемого значения flatMapObservable. Если flatMap возвращает null Observable, подписчик не получит уведомление. Измените оператор возврата на return Observable.just(null);

Но предпочтительнее использовать Observable.fromCallable() для переноса метода longIO(), так что just(1) будет устаревшим, а код будет выглядеть чище. Примечание: возвращаемый тип fromCallable() не равен Observable, поэтому подписчик получит уведомление, даже если возвращается null. Это будет выглядеть так:

Observable.fromCallable(() -> {
        longIO;
        return null;
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
person Aaron He    schedule 25.08.2016

Я думаю, что вы ошибаетесь в нескольких вещах. IMO все ВЫШЕ subscribeOn() будет выполняться в определенном потоке из пула потоков. И, конечно же, все, что НИЖЕ observeOn, должно быть передано в поток пользовательского интерфейса.

Во-вторых, вы не можете сделать так, чтобы ваш оператор flatMap возвращал значение null. Вам нужно вернуть Observable. Если вам не нужно передавать данные, вы можете использовать: Observable.just(null) or Observable.never().

Я думаю, что лучшим решением было бы:

Observable.create(new Observable.OnSubscribe<Object>() {
    @Override
    public void call(final Subscriber<? super Object> subscriber) {
        longIO();
        }
    })
    .startWith(new Object()) //if you want to run it once
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe();
person Piotr Mądry    schedule 28.08.2016