Dev Easy Notes
3.17K subscribers
123 photos
1 video
147 links
Работаю в IT уже 8 лет. Рассказываю про разработку простым языком. Полезность скрыта под тупыми шутками и слоем мата. Лучший underground канал про разработку, который вы сможете найти.

По сотрудничеству писать @haroncode
Download Telegram
Channel created
Привет всем кто забрел на наш канал.🎉 Этот канал для тех, кто интересуется разработкой под android или вообще программированием.

💻 На этом канале мы разбираем разные фундаментальные штуки из мира android, jvm и немного computer science. Эти вещи помогают понять все остальное, вроде современых фреймворков, магию библиотек и общих подходов. 

🧐На канале будет мало новостей с мира android, для этого уже есть Android Broadcast, мы тут собрались чтобы смотреть глубже. Интересно будет тем, кто любит сложные штуки, и хочет понять как они работают. Помогать нам будут два наших персонажа, Хукума и Манифесто.
🔥9👍41
Небольшая затравочка перед нормальными постами🤪
👍2
​​Начнем серию постов с темы: «как работает UI с точки зрения многопоточности🧵».

Представьте прогу с одним потоком, все легко и прозрачно, не нужно думать про многопоточность и про все её проблемы🦄. Однако есть минус, пока прога работает, пользователь просто ждет и ничего не может сделать (напоминает Россию).

Ок, увеличим количество потоков, теперь приложение отзывчивое, и можно делать задачи параллельно, в чем проблема?

Проблема в том, что у нас есть UI слой, на котором мы двигаем и рисуем кнопки, возникает вопрос, как его обновлять из разных потоков? В голову приходит два решения:
☝️Просто сделать все View многопоточными и тогда их можно будет обновлять откуда угодно и не париться.
✌️Выделить для UI один специальных поток, и обновлять только через него.

🦾 Лучшие инженеры в свое время пытались сделать 1-й вариант и все попытки провалились. Как показала практика почти нереально сделать так, чтобы View была многопоточной, было бы безумно сложно не словить DeadLock.

🧐 Представьте что вы на View делаете переменную isAnimationRunning, а теперь она может меняться из разных потоков, сейчас она true, а через мгновение уже false. А если просто навесить по всюду synchronized, то очень сильно просядет производительность.

😅 Со специальным потоком гораздо проще, но вопрос по прежнему актуальный, как менять UI из других потоков? На помощь приходит старый добрый паттерн Consumer/Producer. В частности в Android он реализован за счет троицы пацанов Looper, Handler, MessageQueue, о которых так любят спрашивать на собесах и о которых мы поговорим далее…
👍14👏21
👍1
#android #ui
{1/4} Что такое Looper, как работает и что делает?

🙌 Представьте себе бесконечный цикл, допустим for(;;){}. Далее представим, что в этом цикле мы читаем из некоторой очереди Queue<Runnable> значения и выполняем их, получается что-то вроде:

Queue<Runnable> queue;
for(;;){
final Runnable runnable = queue.take();
runnable.run();
}

Это и есть вся суть Looper. Просто бесконечный цикл который получает из очереди сообщения и их выполняет.

Чтобы создать Looper нужно вызвать метод Looper.prepare(). После этого метод Looper.prepare() сохраняет созданный объект в статическое поле типа ThreadLocal.

Реализация инициализации лупера довольна простая, и при этом позволяет в любом месте программы и из любого треда получить лупер, связанный с текущим тредом. Статический метод Looper.myLooper() просто достает лупер из переменной ThreadLocal.

Далее мы запускаем Looper при помощи метода Looper.loop() он уходит в бесконечный цикл, который мы обсудили выше. В следующих постах обсудим что за сообщения, и кто их посылает.
👍23
👍3😁2
#android #ui
{2/4} В прошлом посте мы поговорили про Looper, там упоминалась некоторая очередь Queue<Runnable>. Давай-те подробнее о ней поговорим.

В реальности есть два отличия:
☝️- это не просто очередь из Collection, это отдельный класс, который так и называется MessageQueue
✌️- внутри очереди не просто Runnable, а специальные объекты, которые называются Message

Начнем с класса Message. В классе есть много полей, но нас сейчас интересует только 3️⃣ это callback, when и next.
callback – тот самый Runnable, который будет исполнен Looper'ом
next - ссылка на следующее сообщение
when - просто поле типа long, которое является 🕑временем, когда это сообщение должно быть выполнено

MessageQueue – простой односвязный список. Если заглянуть в MessageQueue то увидим, что там просто одно поле mMessages типа Message. У каждого Message есть ссылка на следующее сообщение Message.next. Другими словами, MessageQueue хранит только ссылку на первое сообщение.

Сообщения в MessageQueue отсортированы по возрастанию значения поля Message.when. Looper вызывает метод MessageQueue.next() в цикле, и получает отсортированное сообщение, которое нужно выполнить, если же очередь пуста, метод MessageQueue.next() блокирует цикл до тех пор, пока сообщение не появится.

Чтобы положить сообщение в очередь нужно вызвать метод MessageQueue.enqueueMessage(). Метод MessageQueue.enqueueMessage() проходит по очереди, проверяя значение Message.when каждого из сообщений и вставляет новое сообщение в положенное место очереди.

Как создается сообщение? Вручную сообщение лучше не создавать, для создания лучше использовать метод Message.obtain(). Message.obtain() возвращает объект message из пула, который представляет собой связный список максимальным размером 5️⃣0️⃣ сообщений. Если все сообщения пула используются, то Message.obtain() создает и возвращает новый объект Message.
👍4🔥3