Ответ
Работа с сетевыми запросами в MainThread (UI-потоке) приведет к ANR (Application Not Responding), так как сетевые операции блокируют поток. Android запрещает сетевые вызовы в основном потоке начиная с Honeycomb (API 11).
Используй отдельный поток или корутины:
// С корутиной
lifecycleScope.launch(Dispatchers.IO) {
val result = api.getData()
withContext(Dispatchers.Main) {
updateUI(result)
}
}
// С RxJava
api.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result -> updateUI(result) } Ответ 18+ 🔞
О, слушай, тут такая тема, что у меня аж волнение ебать! Представь себе: ты пишешь приложение, всё красиво, кнопочки нажимаются, анимации плавные... И тут — бац! — ты решаешь в основном потоке, прямо там, где интерфейс рисуется, дернуть данные из интернета. Ну, типа, api.getData() прямо в кнопке нажал.
И тут начинается ёперный театр. Приложение просто встаёт колом, как будто его хуй с горы придавил. Экран темнеет, система тебе выдает: "Такое-то приложение не отвечает". Это и есть тот самый ANR, Application Not Responding, ядрёна вошь!
А всё почему? Потому что сетевой запрос — штука медленная, непредсказуемая. Сервер может тупить, связь — хромать. И пока твой запрос ползёт по проводам, главный поток, который должен реагировать на касания и обновлять экран, просто спит. А система Android, начиная ещё с древних времён (Honeycomb, API 11), смотрит на это и говорит: "Ну ты даёшь, чувак! В рот меня чих-пых, так нельзя!" И намертво запрещает сетевые вызовы в UI-потоке.
Так что делать-то? Да похуй, вариантов — овердохуища! Главное — вынести эту тягомотину в фоновый поток.
Смотри, как сейчас модно с корутинами:
// Запускаем в скоупе жизненного цикла (чтоб не утекло)
lifecycleScope.launch(Dispatchers.IO) { // Говорим: "Работай, сука, в фоне!"
val result = api.getData() // Тут можно долго и нудно ждать
withContext(Dispatchers.Main) { // А потом говорим: "А теперь вернись в главный поток!"
updateUI(result) // И только тут лезем в UI
}
}
Красота же? Всё чётко, понятно. Фоновая работа — в Dispatchers.IO, обновление интерфейса — в Dispatchers.Main.
А если ты староват и любишь RxJava, то вот тебе классика, проверенная временем:
api.getData()
.subscribeOn(Schedulers.io()) // "Подписывайся и работай в IO-потоке"
.observeOn(AndroidSchedulers.mainThread()) // "А результат наблюдай в главном"
.subscribe { result -> updateUI(result) } // "И вот тут обновляй UI"
Суть одна: не еби главный поток сетевыми запросами. Вынеси эту работу на сторону, а когда результат будет готов — аккуратно, с поклоном, верни его в UI-поток для отображения. Иначе пользователь тебе такое устроит, что мало не покажется. Сам от себя охуеешь, когда начнут прилетать плохие отзывы!