С чем связано это ограничение, что нельзя обновить view не из UI потока

Ответ

Обновление View не из UI потока может привести к ошибкам, так как Android UI toolkit не является потокобезопасным. Все операции с View должны выполняться в основном потоке (UI потоке), чтобы избежать race conditions и непредсказуемого поведения.

Для обновления UI из фонового потока можно использовать:

runOnUiThread {
    textView.text = "Updated from background"
}
// Или через Handler
Handler(Looper.getMainLooper()).post {
    textView.text = "Updated via Handler"
}
// Или с View.post()
textView.post { textView.text = "Updated via View.post()" }

Ответ 18+ 🔞

А, слушай, вот история про то, как твой фоновый поток пытается ткнуть пальцем в интерфейс. Это, ёпта, классика! Представь: у тебя в приложении всё тихо, красиво, а какой-нибудь AsyncTask или корутина из задней комнаты вдруг решает — а дай-ка я TextView обновлю! И тут начинается ёперный театр.

Android UI toolkit — он, блядь, не для таких гоп-стоп операций сделан. Это как если бы ты в чужую квартиру полез через окно, пока хозяева спят. Волнение ебать, а результат — CalledFromWrongThreadException, или, что хуже, приложение просто накроется медным тазом в самый неподходящий момент. Race conditions, глюки, артефакты — доверия ебать ноль к такому поведению.

Короче, правило простое, как три рубля: всё, что связано с View, должно делаться в главном потоке. Точка.

Ну а если уж очень приспичило из фона что-то поменять, то есть проверенные способы, не надо изобретать хуй с винтом. Смотри:

Самый прямолинейный — runOnUiThread. Как молотком по гвоздю. Находишься в Activity — бей!

runOnUiThread {
    textView.text = "Обновил из подворотни, сука"
}

Чуть более универсальный — Handler с главным Looper. Классика жанра, работает везде.

Handler(Looper.getMainLooper()).post {
    textView.text = "Обновил через старичка Handler"
}

Ну и мой любимый, хитрая жопа — метод post() у самой View. Элегантно и без лишнего шума.

textView.post { textView.text = "Обновил, спросив разрешения у самой вьюхи" }

Выбирай любой, да похуй. Главное — не лезь напрямую. Иначе получишь не обновление, а пиздопроебибну с вылетом, и будешь потом дебажить, бля буду. Запомни: UI — священная корова, трогать её можно только из главного потока. Всё остальное — путь в никуда, блядь.