TGViewer
Dev Easy Notes Dev Easy Notes @dev_easy_notes · 2.91K subscribers
Post #21 1.34K
​​{3/4} В этом посте используется код на Kotlin, просьба Java дИдов не пугаться!

Понемногу у нас с вами складывается картина того, каким образом работает UI в android. Мы разобрали что такое Looper, что такое Message и MessageQueue. Узнали, что в Looper посылаются задачи через MessageQueue. Возникает вопрос❓, как именно послать задачу в Looper, так как прямого доступа к MessageQueue у нас нет. Тут на сцену выходит Handler.

Прежде чем начнем разбирать Handler введем 2️⃣ понятия:
☝️поток consumer - поток, который ждет сообщения, тот, который вызывал Looper.loop().
✌️поток producer - поток, который создает сообщения и посылает их потоку consumer через Handler.
Поток consumer и поток producer могут быть одним потоком, как это может быть разберем далее.

Каждый Android разработчик хотя бы раз в своих проектах использовал Handler. Как уже сказано выше, нужен он для того, чтобы посылать задачи из потока producer в поток consumer.

У Handler есть несколько конструкторов, интересные пожалуй только 2️⃣ это:
☝️дефолтый коструктор без аргументов Handler()
✌️конструктор с аргументом типа Looper Handler(looper: Looper)

Когда используют конструктор без Looper, Handler пытается найти его через Looper.myLooper() и если его не находит, то падает❌.
Допустим в Activity.onCreate вы вызовете Handler().post{ doSmth() } - тут создается Handler, который через метод Looper.myLooper() получает Looper который привязан к Main Thread🧶, что аналогично записи Handler(Looper.getMainLooper()).post{ doSmth() }. Но если попытаемся тоже самое сделать на потоке без Looper, конструктор упадет💣:

Thread {
val handler = Handler() // - тут мы упадем
❌, так как у этого потока нет Looper🔁, подробнее смотри в посте про Looper
handler.post { doSmth() }
}.start()

Конструктор с входным параметром в виде Looper предпочтительнее, так как тогда вы явно задаете Looper🔁, в который будут post’иться сообщения. С ним все довольно очевидно, на вход нужно подать Looper в который будут посылаться задачи.

Теперь посмотрим на слудующий кусок кода:

fun onCreate() { // этот метод вызывает система
Handler().post {
Log.d("hello from handler thread ${Thread.currentThread().name}")
}
Log.d("hello from onCreate thread ${Thread.currentThread().name}")
}

Для начала попробуйте ответить сами, что будет выведено в лог❓ В логах мы увидим следующую последовательность:

- "hello from onCreate thread main"
- "hello from handler thread main"

Когда вызываем метод post, переданный Runnable оборачивается в Message и через MessageQueue подается на Looper consumer потока. Однако система все методы жизненного цикла активности тоже вызывает через Looper потока Main🧶, даже сам метод onCreate() вызывался примерно так:

val activity = getCurrentActivity()
val handler = Handler()
handler.post {
activity.onCreate()
}

Следовательно, когда мы вызываем Handler().post{ Log.d("hello from handler thread ${Thread.currentThread().name}") } эта задача кладется в очередь и выполнится после того, как завершится метод onCreate().

Этот пример очень сильное упрощение того, что происходит на самом деле, но суть та же. Это тот случай, когда поток consumer и поток producer это один и тот же поток. Именно этим фактом, обуславливается асинхронность в UI. Когда мы создаем транзакцию для показа фрагмента, после метода commit эта транзакция также кладется в MessageQueue через Handler, и выполняется позже Looper’ом Main Thread🧶, также происходит и с показом новой🆕 Activity и многими другими вещами вроде анимаций и т.п.

Стоит упомянуть еще одну интересную особенность, так уж вышло, что огромное количество багов связаных с View на Android можно решить просто отложив задачу Handler().postDelayed(100) { //doSmth }.

Помните мы разбирали, что у Message есть специальное поле when, так вот, когда вызываем post у Handler, там используется SystemClock.uptimeMillis()), наподобие System.getCurrentTimeMillis(), а когда вызываем postDelayed, то входной аргумент delay прибавляется к SystemClock.uptimeMillis()) и записывается в поле when, а дальше магия сортировки, которая обсуждалась туть.
  • 👍 24
  • ❤ 1
  • 🔥 1
More from @dev_easy_notes
  1. Sep 24, 2026На всякий случай напомню напомню, если такую хуйню видите, сразу в бан кидаете. Вы скорее…
  2. Aug 4, 2026Короче, поясню, я давно ничего не пишу, потому что заебался) возможно я скоро вернусь, как…
  3. Aug 4, 2026Post #596
  4. Apr 17, 2026Меня вот что еще дико бесит, через год я буду уже как 10 лет в индустрии и все равно, кажд…
  5. Apr 15, 2026video post
  6. Apr 9, 2026Как оценить работу модели? Часто вижу высказывания в стиле: вот новый клод стал тупее, или…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →