Что такое метод observeOn

Ответ

observeOn в RxJava определяет, на каком потоке будут обрабатываться события (onNext, onError, onComplete).

Пример:

Observable.just(1, 2, 3)
    .subscribeOn(Schedulers.io()) // Запускает выполнение в IO-потоке
    .observeOn(AndroidSchedulers.mainThread()) // Переключает обработку на главный поток
    .subscribe { value -> 
        // UI-операции (например, обновление TextView)
    }

Нюансы:

  • Влияет только на последующие операторы.
  • Если не указан, обработка продолжится на том же потоке, что и subscribeOn.
  • Часто используется для UI-обновлений (mainThread).
  • Может приводить к NetworkOnMainThreadException, если забыть переключить поток перед сетевой операцией.

Ответ 18+ 🔞

А, слушай, про observeOn! Ну это вообще классика, ебать мои старые костыли. Представь себе конвейер.

Вот ты на фабрике делаешь детали (subscribeOn(Schedulers.io()) — где-то в цеху, в грязи и шуме). А потом готовую, чистенькую деталь нужно отнести в красивый выставочный зал, чтобы директору показать. Вот этот самый observeOn(AndroidSchedulers.mainThread()) — это как раз телепорт с конвейера прямо в белый зал с хрустальными люстрами.

Короче, пример, чтоб совсем понятно было:

Observable.just(1, 2, 3) // Берём цифры
    .subscribeOn(Schedulers.io()) // Всё это дело крутим-вертим в каком-то фоновом потоке (IO)
    .observeOn(AndroidSchedulers.mainThread()) // А ВОТ ТУТ, ёпта, говорим: "ВСЁ, что ДАЛЬШЕ — тащи на главный поток!"
    .subscribe { value ->
        // И вот тут мы уже в UI-потоке, можно спокойно TextView тыкать, не боясь, что приложение рухнет.
        textView.text = "Пришло: $value"
    }

А теперь нюансы, на которых все обжигаются, хитрая жопа эта система:

  1. Влияет только на то, что ПОСЛЕ него. Это ключевое! Если ты поставишь observeOn в начале цепочки, а потом сделаешь какую-то тяжёлую операцию map, которая парсит JSON размером с Библию, то эта операция всё равно будет выполняться на том потоке, который был ДО observeOn. Он не откатывает всё назад. Он говорит: "Ладно, ребята, дальше работаем там-то".

  2. Если его не поставить вообще, то подписчик (subscribe) будет получать события на том же потоке, где и subscribeOn запустил выполнение. То есть если subscribeOn был на Schedulers.io(), то и в subscribe ты окажешься в фоне. Попробуй там тронуть UI — получишь NetworkOnMainThreadException (или его аналог), даже если сети рядом не было. Приложение просто вылетит, и будет тебе хиросима.

  3. Для UI — святое дело. observeOn(AndroidSchedulers.mainThread()) — это как мантра перед любым обновлением вьюхи. Без этого — пизда рулю.

  4. Про NetworkOnMainThreadException. Вот типичная лажа новичка:

    api.getData()
        .subscribeOn(Schedulers.io())
        .subscribe { data ->
            // ОЙ! А `observeOn` забыли! Мы всё ещё в IO-потоке, но пытаемся в UI лезть.
            updateUI(data) // CRASH! NetworkOnMainThreadException, хотя мы не сеть дергаем, но поток не главный.
        }

    Чисто технически исключение называется так, потому что раньше чаще всего сетевые вызовы в основном потоке и блокировали. Сейчас оно вылетает за любую работу с сетью (или просто долгую операцию) не в том потоке. Так что да, доверия ебать ноль к потокам — всегда явно указывай, где что должно крутиться.

Короче, правило простое: subscribeOnгде делать работу, observeOnгде получить результат. Перепутал — сам от себя охуеешь, когда приложение на ровном месте крашиться начнёт.