<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>NooboDroid</title><subtitle>Пародист android-разработчика. Пишу в тви плоские шутки, а сюда - заметки. Чего не знаю - того не знаю, а не знаю я практически ничего!</subtitle><author><name>NooboDroid</name></author><id>https://teletype.in/atom/noobodroid</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/noobodroid?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/noobodroid?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-04T22:29:19.663Z</updated><entry><id>noobodroid:WBZCQSaG8eI</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/WBZCQSaG8eI?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Aliexpress для рабочего места</title><published>2021-11-23T17:51:25.746Z</published><updated>2021-11-23T18:05:45.927Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/67/36/67362063-029b-44b6-887d-5abf2be9f851.jpeg"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/d5/35/d535ca13-05fb-44cd-a921-1f0aea29c244.jpeg&quot;&gt;У меня сейчас довольно нагруженный период и до написания технических заметок нет ни сил, ни вдохновения, поэтому решил сделать подборку всяких товаров с Aliexpress, какими пользуюсь сам, может кому-то что-то приглянется. В подборку войдут не только полезности, но и приятности, по возможности упомяну нюансы, которые могут всплыть при выборе.</summary><content type="html">
  &lt;figure id=&quot;WaVI&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d5/35/d535ca13-05fb-44cd-a921-1f0aea29c244.jpeg&quot; width=&quot;900&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iv1X&quot;&gt;У меня сейчас довольно нагруженный период и до написания технических заметок нет ни сил, ни вдохновения, поэтому решил сделать подборку всяких товаров с Aliexpress, какими пользуюсь сам, может кому-то что-то приглянется. В подборку войдут не только полезности, но и приятности, по возможности упомяну нюансы, которые могут всплыть при выборе.&lt;/p&gt;
  &lt;p id=&quot;hgc6&quot;&gt;Постараюсь сделать подборку из не самых очевидных вещей, поэтому всякие кабели, коробки и сумки сюда не войдут.&lt;/p&gt;
  &lt;p id=&quot;rv3t&quot;&gt;Ссылки на конкретные товары прикреплять не буду, по заголовку будет понятно, как найти тот или иной товар.&lt;/p&gt;
  &lt;h3 id=&quot;zxE6&quot; data-align=&quot;center&quot;&gt;1. Подставка для монитора&lt;/h3&gt;
  &lt;figure id=&quot;l2S2&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/8c/b5/8cb5a854-d318-45d3-9e78-85e6e2e6b4c5.jpeg&quot; width=&quot;640&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;JXwD&quot;&gt;Здесь все просто и без нюансов. Мне хотелось из алюминия, но существует куча разных вариантов и в том числе варианты из дерева и абсолютно разных размеров.&lt;/p&gt;
  &lt;h3 id=&quot;uJ3N&quot; data-align=&quot;center&quot;&gt;2. Полка на монитор&lt;/h3&gt;
  &lt;figure id=&quot;9U0w&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/20/32/2032d2ca-4dee-47b8-a62d-a978cb55dcae.jpeg&quot; width=&quot;900&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;udsZ&quot;&gt;Поразился находчивости людей, каким пришла в голову идея данного изобретения и как полка для роутера и какой-нибудь мелочи - отличный вариант, что позволяет сэкономить место непосредственно на столе.&lt;/p&gt;
  &lt;h3 id=&quot;UzrT&quot; data-align=&quot;center&quot;&gt;3. Огромный коврик для мыши&lt;/h3&gt;
  &lt;figure id=&quot;w5K3&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/92/54/92545fb2-32de-4147-afce-a6118a84418d.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;FhZ5&quot;&gt;Очень приятно с таким работать и размеры ковриков иногда встречаются огромнейшие. Можно найти как монотонные варианты, так и с прикольным принтом.&lt;/p&gt;
  &lt;h3 id=&quot;gPUg&quot; data-align=&quot;center&quot;&gt;4. USB регулятор громкости&lt;/h3&gt;
  &lt;figure id=&quot;plCf&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/34/86/3486ae7e-5e46-432f-bad6-b52c6e917623.jpeg&quot; width=&quot;1000&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;x3IN&quot;&gt;До моих колонок ручка регулировки уровня звука расположена сзади и лезть туда неудобно. Поэтому отличное решение.&lt;/p&gt;
  &lt;h3 id=&quot;Yioz&quot; data-align=&quot;center&quot;&gt;5. Подставка для телефона&lt;/h3&gt;
  &lt;figure id=&quot;SXwY&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/85/a1/85a16a6f-c627-4a5c-a3af-bdfc2660afb1.jpeg&quot; width=&quot;790&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;uVZl&quot;&gt;Часто тестирую свой код на реальном девайсе и такая штука топово помогает. Определенно лучше, чем с девайсом, лежащим на столе.&lt;/p&gt;
  &lt;h3 id=&quot;LMgD&quot; data-align=&quot;center&quot;&gt;6. Ящик для хранения кабелей&lt;/h3&gt;
  &lt;figure id=&quot;0Ih4&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/17/63/1763c087-a9dd-4d71-92f7-6b5e9fb528a9.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hqfy&quot;&gt;Крепкая штука. У меня такая расположена на полу и в ней сетевой фильтр. Стоит недешево для куска крепкого пластика и фанеры, но мне слишком надоела пыль в гнездах сетевого фильтра.&lt;/p&gt;
  &lt;h3 id=&quot;JIhU&quot; data-align=&quot;center&quot;&gt;7. Силиконовая скатерть для стола&lt;/h3&gt;
  &lt;figure id=&quot;KFxw&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b9/1b/b91bd946-b0f2-4775-bba3-042e0040f6cc.png&quot; width=&quot;1086&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;rhzd&quot;&gt;Существует просто огромных и разных размеров и я смог найти подходящую под свой немалый стол, чему доволен, ведь на самом столе системник и колонки, да и в принципе царапать стол не хочется. При толщине в 1-2мм у пленки нет мягкости и на ней даже удобно писать и ничего не подкладывать.&lt;/p&gt;
  &lt;h3 id=&quot;1pee&quot; data-align=&quot;center&quot;&gt;8. Органайзер для кабеля&lt;/h3&gt;
  &lt;figure id=&quot;Jtbi&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/96/f2/96f232a9-54e9-42c5-a431-a8bae5b156a7.jpeg&quot; width=&quot;1000&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;D2SU&quot;&gt;Тут и лишних слов не надо.&lt;/p&gt;
  &lt;h3 id=&quot;vPPn&quot; data-align=&quot;center&quot;&gt;9.1 Стяжка&lt;/h3&gt;
  &lt;figure id=&quot;ql1w&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c3/47/c347e26b-f0e3-48e0-8391-4797cd1bda38.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;Yf6t&quot; data-align=&quot;center&quot;&gt;9.2 Стяжка&lt;/h3&gt;
  &lt;figure id=&quot;HaM9&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/fd/31/fd31b07a-a429-42f0-8cd8-c8b74c342362.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;Rgt3&quot; data-align=&quot;center&quot;&gt;10. Подставка для наушников&lt;/h3&gt;
  &lt;figure id=&quot;eiL6&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/af/74/af74b332-8338-4a3a-b3b7-cbe23f852f0f.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;jFru&quot; data-align=&quot;center&quot;&gt;11. Стол на кровать для ноутбука &lt;/h3&gt;
  &lt;figure id=&quot;G8bN&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/83/89/83890a47-ca5b-4539-a565-39e67707cb55.jpeg&quot; width=&quot;1664&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;WpFW&quot;&gt;Скажу честно: используется редко. Но иногда возможность перенести рабочее пространство на кровать - очень кстати!&lt;/p&gt;
  &lt;h3 id=&quot;WSFR&quot; data-align=&quot;center&quot;&gt;12. Подвесной органайзер&lt;/h3&gt;
  &lt;figure id=&quot;3vE2&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/bd/4b/bd4bfc18-7378-4610-bb8f-263965a9c061.jpeg&quot; width=&quot;900&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3Bez&quot;&gt;Иногда есть куча вещей, которым не место под рукой, но при этом далеко убирать не хочется. И это вполне решение. Не сказать, что смотрится как исключительно кухонный вариант.&lt;/p&gt;
  &lt;h3 id=&quot;E3zI&quot; data-align=&quot;center&quot;&gt;13. Светодиодная лента&lt;/h3&gt;
  &lt;figure id=&quot;kfd9&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0a/70/0a70fffe-1d65-4194-b5b2-8a74ac7b0dde.jpeg&quot; width=&quot;1000&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;CJg6&quot;&gt;Не относится к организации, но дает приятный бонус к атмосфере. Лента самоклеящаяся. Можно найти экземпляры с оклееной стороной от известного бренда 3М. Управляются разными способами: от блютус до пульта. Есть варианты для подключения через USB, а есть с питанием от сети. &lt;strong&gt;Главный нюанс выбора: как правило ленты двух типов - с цифрами 2835 или 5050. &lt;/strong&gt;Разница в цене минимальна, но светодиоды расположены нормально именно у второго варианта, в едином блоке. В первом варианте нужный цвет будет получаться при смешении диодов, что расположены далеко друг от друга и если вашу ленту что-то перекрывает, то вместо выбранного света получите лишь радугу.&lt;/p&gt;
  &lt;h2 id=&quot;W0ve&quot; data-align=&quot;center&quot;&gt;ФИНАЛ&lt;/h2&gt;
  &lt;p id=&quot;Nmhl&quot;&gt;Для тех, кто дошел до конца - выкладываю главные товары, что мне очень помогли организовать свое место. Какая моя была главная идея при организации рабочего места: избавиться от старого маленького стола и сделать все так, чтобы удобно было работать. Так как мне очень важен психологический момент закрытия крышки рабочего ноута, дабы переключиться в другой контекст, то мысленно закладывал идею, что нужно шэрить изображение на монитор, не плодить большое количество мониторов и в этом мне помогли больше всего последние две вещи.&lt;/p&gt;
  &lt;h3 id=&quot;fEzB&quot; data-align=&quot;center&quot;&gt;14. Настольная подставка для ноутбука &lt;/h3&gt;
  &lt;figure id=&quot;tEiN&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f1/d4/f1d43e7e-6c20-4cd2-9430-db18f13de454.jpeg&quot; width=&quot;1000&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;u4Q9&quot;&gt;Позволяет чуть более компактно ноутбуку разместиться на столе, да и подставка спокойно складывается и убирается подальше после окончания рабочего времени.&lt;/p&gt;
  &lt;h3 id=&quot;W5dt&quot; data-align=&quot;center&quot;&gt;15. HDMI сплиттер&lt;/h3&gt;
  &lt;figure id=&quot;Bwhi&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/87/58/87586aab-ea38-4e1e-bded-e2223c223606.jpeg&quot; width=&quot;1000&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iTRA&quot;&gt;То, что помогло по сути организовать всё, как и хотелось. В стационарник и ноутбук идут HDMI и USB кабели (mother USB -  father USB type C). Из сплиттера выходит HDMI в монитор. И все готово для того, чтобы перебрасывать по мере надобности изображение на мониторе то с ноутбука, то с ПК - по одному лишь клику на кнопку.&lt;/p&gt;
  &lt;p id=&quot;5HTD&quot;&gt;Самое главное не промахнуться со сплиттером. Они бывают двунаправленные и первая моя попытка покупки сплиттера была неудачной, так как по HDMI шел ток и тем самым вращал вентиляторы на видеокарте, на корпусе и кулер. Поэтому нужен именно однонаправленный, а лучше ищите тот, который приложил сюда в заметку.&lt;/p&gt;
  &lt;h3 id=&quot;6ZJs&quot; data-align=&quot;center&quot;&gt;ЭПИЛОГ&lt;/h3&gt;
  &lt;p id=&quot;4V1m&quot;&gt;В заметку не вошло много всякого разного, но итак вышло все довольно объемно. Надеюсь, что минимум натолкнул на какую-то идею для поиска полезностей, что помогут организовать рабочее пространство. И отдельный респект тем, кто дошел аж до эпилога!&lt;/p&gt;

</content></entry><entry><id>noobodroid:hgt--QlAUXL</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/hgt--QlAUXL?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Android-NoobLabs: RxJava2 и Kotlin Coroutines</title><published>2021-09-03T15:44:53.030Z</published><updated>2021-09-04T09:38:13.392Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/b9/c9/b9c9d3fe-e5a6-413c-8c4d-a241ed56d31c.jpeg"></media:thumbnail><category term="android" label="Android"></category><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/d2/4b/d24b9b43-e0f1-4e44-b583-a690d9ded735.jpeg&quot;&gt;Это заметка для зеленых новичков. Не самые зеленые и не самые новички - давно уже попробовали руками все сами. В данной заметке я буду использовать: Dagger Hilt, RxJava2, Kotlin Coroutines и Retrofit2. Dagger Hilt задействован исключительно для МОЕГО удобства, строго не рекомендую начинать познавать Dagger с Hilta, потому что сокращена куча boiler-plate'а, которая дает понимание принципов работы Dagger'а, поэтому это лишь помощь мне, чтоб не плодить совсем дикий щиткод в примерах, за который вам отобьют руки всей бригадой за который отклонят в будущем ваши pull-request'ы.</summary><content type="html">
  &lt;figure id=&quot;u9oo&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d2/4b/d24b9b43-e0f1-4e44-b583-a690d9ded735.jpeg&quot; width=&quot;1024&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;Fr46&quot; data-align=&quot;center&quot;&gt;И зачем это все надо?&lt;/h2&gt;
  &lt;p id=&quot;bojr&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;OC1R&quot;&gt;Это заметка для зеленых новичков. Не самые зеленые и не самые новички - давно уже попробовали руками все сами. В данной заметке я буду использовать: Dagger Hilt, RxJava2, Kotlin Coroutines и Retrofit2. Dagger Hilt задействован исключительно для МОЕГО удобства, строго не рекомендую начинать познавать Dagger с Hilta, потому что сокращена куча boiler-plate&amp;#x27;а, которая дает понимание принципов работы Dagger&amp;#x27;а, поэтому это лишь помощь мне, чтоб не плодить совсем дикий щиткод в примерах, &lt;s&gt;за который вам отобьют руки всей бригадой&lt;/s&gt; за который отклонят в будущем ваши pull-request&amp;#x27;ы.&lt;/p&gt;
  &lt;p id=&quot;9RLU&quot;&gt;&lt;/p&gt;
  &lt;h2 data-align=&quot;center&quot; id=&quot;R32q&quot;&gt;Y-нылое введение&lt;/h2&gt;
  &lt;p id=&quot;eJ74&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;8bHN&quot; class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/ff/52/ff52e4f1-7012-4688-8aed-7b27153adc72.jpeg&quot; width=&quot;750&quot; /&gt;
    &lt;figcaption&gt;Это итак все знают, ну чо ты делаешь?&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;J6kv&quot;&gt;Начну с определений.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;blockquote id=&quot;e6MZ&quot;&gt;&lt;strong&gt;RxJava - это реализация библиотеки ReactiveX с открытым исходным кодом, которая помогает создавать приложения в стиле реактивного программирования. &lt;/strong&gt;&lt;/blockquote&gt;
  &lt;/section&gt;
  &lt;p id=&quot;qCgt&quot;&gt;И изначально основное предназначение было именно в этом, а не в том, что в этом вашем Android&amp;#x27;е вы ей только потоки переключаете, &lt;s&gt;негодники и негодницы&lt;/s&gt; господа  и дамы.&lt;/p&gt;
  &lt;p id=&quot;RGkq&quot;&gt;С Kotlin Coroutines - все сложнее. Чтобы в них разобраться - надо английский знать, поэтому обращаемся к русскоязычной документации:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;blockquote id=&quot;y8lm&quot;&gt;&lt;strong&gt;Сопрограммы - это легковесные потоки. Сопрограммы обеспечивают возможность избежать блокировки исполняющегося потока путём использования более дешёвой и управляемой операции: приостановки (suspend) сопрограммы.&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;/section&gt;
  &lt;p id=&quot;xD3c&quot;&gt;И тяжелее всего осознать, как практически обеспечивается эта самая легковесность. Что есть еще на эту тему в доке:&lt;/p&gt;
  &lt;figure id=&quot;a1y8&quot; class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/94/1b/941b3c76-5bf9-4e7b-9bbb-6e8966ffe3d9.png&quot; width=&quot;785&quot; /&gt;
    &lt;figcaption&gt;Это скрин, не советую пытаться копипастить код&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mGSM&quot;&gt;Теперь переходим к практике.&lt;/p&gt;
  &lt;p id=&quot;5Wwe&quot;&gt;&lt;/p&gt;
  &lt;h2 data-align=&quot;center&quot; id=&quot;p5eU&quot;&gt;Что делаю и как будет выглядеть?&lt;/h2&gt;
  &lt;p id=&quot;N6vN&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;3xhT&quot;&gt;В качестве полигона буду делать приложение с единственной Activity, что имеет некую ViewModel, которая содержит DataSource-класс (не хотелось обзывать Repository). DataSource что является источником данных и представляем, что этот класс будет нужен на уровне всего приложения. В качестве источника данных буду использовать сторонее API из &lt;a href=&quot;https://github.com/public-apis/public-apis&quot; target=&quot;_blank&quot;&gt;списка публичных API&lt;/a&gt;. И буду поэтапно дергать сетевые запросы: сначала через RxJava2, потом через Coroutines, причем даже не буду ничего делать в UI-слое, ведь задача просто успешно сделать сетевые запросы через разные инструменты и увидеть информацию в логе.&lt;/p&gt;
  &lt;p id=&quot;V5ev&quot;&gt;Меньше слов и больше дела! Поехали!&lt;/p&gt;
  &lt;p id=&quot;lDp6&quot;&gt;&lt;/p&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;WHe6&quot;&gt;Акт нулевой: затаскиваем зависимости в проект&lt;/h3&gt;
  &lt;p id=&quot;XNMh&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;vUBg&quot;&gt;Студия сгенерировала пустой проект. Начинаем добавлять все нужные зависимости.&lt;/p&gt;
  &lt;p id=&quot;kxLK&quot;&gt;1. В build.gradle проекта:&lt;/p&gt;
  &lt;pre data-lang=&quot;groovy&quot; id=&quot;RyhG&quot;&gt;...
dependencies {    
...   
classpath &amp;#x27;com.google.dagger:hilt-android-gradle-plugin:2.38.1&amp;#x27;
...
}
...&lt;/pre&gt;
  &lt;p id=&quot;dhqH&quot;&gt;2. В  build.gradle модуля:&lt;/p&gt;
  &lt;pre data-lang=&quot;groovy&quot; id=&quot;qTQI&quot;&gt;
plugins {    
...    
id &amp;#x27;kotlin-kapt&amp;#x27;    
id &amp;#x27;dagger.hilt.android.plugin&amp;#x27;
}

dependencies {
...
implementation &amp;#x27;androidx.fragment:fragment-ktx:1.3.6&amp;#x27; // for by viewModels()

//Rx Java2
implementation &amp;#x27;io.reactivex.rxjava2:rxandroid:2.1.1&amp;#x27;
implementation &amp;#x27;io.reactivex.rxjava2:rxjava:2.2.9&amp;#x27;

//Coroutines
def coroutines = &amp;quot;1.5.1-native-mt&amp;quot;
implementation &amp;quot;org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines&amp;quot;
implementation &amp;quot;org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines&amp;quot;

//retrofit 2
def retrofit2 = &amp;quot;2.9.0&amp;quot;
implementation &amp;quot;com.squareup.retrofit2:retrofit:$retrofit2&amp;quot;
implementation &amp;quot;com.squareup.retrofit2:converter-gson:$retrofit2&amp;quot;
implementation &amp;quot;com.squareup.retrofit2:adapter-rxjava2:2.4.0&amp;quot;

//Dagger Hilt
def daggerHilt = &amp;quot;2.38&amp;quot;
implementation &amp;quot;com.google.dagger:hilt-android:$daggerHilt&amp;quot;
kapt &amp;quot;com.google.dagger:hilt-compiler:$daggerHilt&amp;quot;

}
&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;gJ3S&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;YNCW&quot;&gt;Акт первый: закладываем основы основ&lt;/h3&gt;
  &lt;p id=&quot;4wB4&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;8HKE&quot;&gt;Создаем сущность Data-класса, что будет возвращаться по запросу:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;8t1R&quot;&gt;data class Fact(    
   val fact: String
)&lt;/pre&gt;
  &lt;p id=&quot;QRaR&quot;&gt;Создаем API-интерфейс Retrofit&amp;#x27;а для RxJava2:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;8Hsm&quot;&gt;interface ApiRx {    

   @GET(&amp;quot;resources/dogs/all&amp;quot;)    
   fun getAllFactsRx() : Single&amp;lt;List&amp;lt;Fact&amp;gt;&amp;gt;    
  
   companion object {
           
      private const val BASE_URL 
      = &amp;quot;https://dog-facts-api.herokuapp.com/api/v1/&amp;quot; 
             
      private var gson = GsonBuilder()            
         .setLenient()            
         .create()        
   
      var retrofit: Retrofit = Retrofit.Builder()            
          .baseUrl(BASE_URL)            
          .addConverterFactory(GsonConverterFactory.create(gson))            
          .addCallAdapterFactory(RxJava2CallAdapterFactory.create())            
          .build()    
   }
}&lt;/pre&gt;
  &lt;p id=&quot;3zJO&quot;&gt;Создаем API-интерфейс Retrofit&amp;#x27;а для Kotlin Coroutines:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;1CcK&quot;&gt;interface ApiCoroutines {    

   @GET(&amp;quot;resources/dogs/all&amp;quot;)    
   suspend fun getAllFactsCoroutines() : List&amp;lt;Fact&amp;gt;  
  
   companion object {
           
      private const val BASE_URL 
      = &amp;quot;https://dog-facts-api.herokuapp.com/api/v1/&amp;quot; 
             
      private var gson = GsonBuilder()            
         .setLenient()            
         .create()        
   
      var retrofit: Retrofit = Retrofit.Builder()            
          .baseUrl(BASE_URL)            
          .addConverterFactory(GsonConverterFactory.create(gson))                       
          .build()    
   }
}&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;Z3FV&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;GQBA&quot;&gt;Акт второй: основы для Dagger&amp;#x27;а&lt;/h3&gt;
  &lt;p id=&quot;3ikV&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;0MUZ&quot;&gt;В первую очередь создаем класс App, помечаем аннотацией, добавляем Permission для Internet&amp;#x27;а и регистрируем в manifest&amp;#x27;е:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;8agl&quot;&gt;@HiltAndroidAppclass 
App : Application()&lt;/pre&gt;
  &lt;pre data-lang=&quot;xml&quot; id=&quot;Wleb&quot;&gt;...
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;
&amp;lt;application
...
android:name=&amp;quot;.App&amp;quot;
&amp;lt;/application&amp;gt;
...&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;EWZO&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;EI7W&quot;&gt;Акт третий: создаем класс DataSource, ViewModel и дописываем коллбэк в Activity&lt;/h3&gt;
  &lt;p id=&quot;EKKA&quot;&gt;&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;qvhZ&quot;&gt;class DataSource(    
   private val apiRx: ApiRx,    
   private val apiCoroutines: ApiCoroutines
) {
 
}&lt;/pre&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;0P8a&quot;&gt;@HiltViewModel
class MainViewModel @Inject constructor(    
   private val dataSource: DataSource
) : ViewModel() {
 
   fun onCreate() {
   
   }
   
   private fun fetchDataRx() {
   
   }
   
   private fun fetchDataCoroutines() {
   
   }
}&lt;/pre&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;t9pT&quot;&gt;@AndroidEntryPointclass 
MainActivity : AppCompatActivity() {    

   private val viewModel: MainViewModel by viewModels()    
   
   override fun onCreate(savedInstanceState: Bundle?) {        
       super.onCreate(savedInstanceState)        
       setContentView(R.layout.activity_main)        
       viewModel.onCreate()    
   }
}&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;svBM&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;Kuuc&quot;&gt;Акт четвертый: создаем компонент приложения&lt;/h3&gt;
  &lt;p id=&quot;yREQ&quot;&gt;&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;TYDz&quot;&gt;@Module
@InstallIn(SingletonComponent::class)
class AppComponent {    
   @Provides    
   fun providesApiCoroutines()    
   = ApiCoroutines.retrofit.create(ApiCoroutines::class.java)   
    
   @Provides    
   fun providesApiRx()    
   = ApiRx.retrofit.create(ApiRx::class.java)    
   
   @Provides    
   @Singleton    
   fun providesDataSource(apiRx: ApiRx, apiCoroutines: ApiCoroutines)    
   = DataSource(apiRx, apiCoroutines)
}&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;LSr1&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;gOwf&quot;&gt;Акт пятый: дергаем API через RXJava2&lt;/h3&gt;
  &lt;p id=&quot;0IUy&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;jDXM&quot;&gt;Начинаем с DataSource, добавляем туда функцию:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;6Ql1&quot;&gt;fun getFactsRx() : Single&amp;lt;List&amp;lt;Fact&amp;gt;&amp;gt; {    
   return apiRx.getAllFactsRx()
}&lt;/pre&gt;
  &lt;p id=&quot;5TKa&quot;&gt;Переходим к MainViewModel, где нужно выполнить подписку на событие:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;kuMq&quot;&gt;...
fun onCreate() {        
   fetchDataRx()           
}
 
@SuppressLint(&amp;quot;CheckResult&amp;quot;)
private fun fetchDataRx() {      
   dataSource.getFactsRx()            
      .subscribe({                
          Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;Success: $it&amp;quot;)            
      }, {                
          Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;Error: $it&amp;quot;)            
      })    
}
...&lt;/pre&gt;
  &lt;p id=&quot;922l&quot;&gt;Суровые синьоры со стажем догадались, что вывелось в консоль!&lt;/p&gt;
  &lt;pre id=&quot;ohNs&quot;&gt;MainViewModelDebug: Error: android.os.NetworkOnMainThreadException&lt;/pre&gt;
  &lt;p id=&quot;EQTi&quot;&gt;&lt;/p&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;4S44&quot;&gt;Акт шестой: разбираемся, что пошло не так&lt;/h3&gt;
  &lt;p id=&quot;hetK&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;wh61&quot;&gt;Цитирую отличную выжимку статьи с сайта &lt;a href=&quot;https://xakep.ru/2016/06/01/android-multithreading-1/#toc02.&quot; target=&quot;_blank&quot;&gt;xakep.ru&lt;/a&gt;, которая всё объясняет:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;blockquote id=&quot;TXqb&quot;&gt;Запущенное в Android приложение имеет собственный процесс и как минимум один поток — так называемый главный поток (main thread). Если в приложении есть какие-либо визуальные элементы, то в этом потоке запускается объект класса Activity, отвечающий за отрисовку на дисплее интерфейса (user interface, UI). &lt;/blockquote&gt;
    &lt;blockquote id=&quot;631V&quot;&gt;В главном Activity должно быть как можно меньше вычислений, единственная его задача — отображать UI. Если главный поток будет занят подсчетом числа пи, то он потеряет связь с пользователем — пока число не досчиталось, Activity не сможет обрабатывать запросы пользователя и со стороны будет казаться, что приложение зависло. Если ожидание продлится чуть больше пары секунд, ОС Android это заметит и пользователь увидит сообщение ANR (application not responding — «приложение не отвечает») с предложением принудительно завершить приложение.&lt;/blockquote&gt;
  &lt;/section&gt;
  &lt;p id=&quot;1uCj&quot;&gt;&lt;/p&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;aYFh&quot;&gt;Акт седьмой: дергаем API через RXJava, но теперь корректно&lt;/h3&gt;
  &lt;p id=&quot;TTJf&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;JS2S&quot;&gt;Добавляем важные строки, которых не хватало. Фактически эти две строки можно интерпретировать так: оператор создания subscribeOn приказывает выполниться методу getAllFactsRx() в отдельном IO-потоке, а оператор observeOn передает результат выполнения в Main-thread Android&amp;#x27;а:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;mJtx&quot;&gt;fun getFactsRx() : Single&amp;lt;List&amp;lt;Fact&amp;gt;&amp;gt; {    
   return apiRx.getAllFactsRx()
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
}&lt;/pre&gt;
  &lt;p id=&quot;4ZKu&quot;&gt;Смотрим лог, и там пришел ответ сервера, значит всё вандефульно:&lt;/p&gt;
  &lt;pre id=&quot;hXjg&quot;&gt;MainViewModelDebug: Success: [Fact(fact=All dogs can be traced ...&lt;/pre&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;wlM2&quot;&gt;&lt;/h3&gt;
  &lt;h3 data-align=&quot;center&quot; id=&quot;7iTw&quot;&gt;Акт восьмой: дергаем API через Coroutines&lt;/h3&gt;
  &lt;p id=&quot;KNKc&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;K8Y6&quot;&gt;Идем в DataSource и аналогично Rx добавляем функцию:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;6Tn2&quot;&gt;suspend fun getFactsCoroutines() : List&amp;lt;Fact&amp;gt; {    
    return apiCoroutines.getAllFactsCoroutines()
}&lt;/pre&gt;
  &lt;p id=&quot;5JC0&quot;&gt;И вызываем метод из ViewModel:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot; id=&quot;jPMR&quot;&gt;...
fun onCreate() {
   //fetchDataRx()        
   fetchDataCoroutines()    
}
 
private fun fetchDataCoroutines() {    
   val exceptionHandler = CoroutineExceptionHandler { _, it -&amp;gt;        
      Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;Error: $it&amp;quot;)    
   }    
   viewModelScope.launch(exceptionHandler) {        
      val resultGetFacts = dataSource.getFactsCoroutines()        
      Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;Success: $resultGetFacts&amp;quot;)    
   }
}
...&lt;/pre&gt;
  &lt;p id=&quot;mcAp&quot;&gt;Смотрим лог:&lt;/p&gt;
  &lt;pre id=&quot;mw9s&quot;&gt;MainViewModelDebug: Success: [Fact(fact=All dogs can be traced...&lt;/pre&gt;
  &lt;p id=&quot;poBR&quot;&gt;И здесь нужно остановиться и подумать. Что упущено относительно RxJava2?&lt;/p&gt;
  &lt;p id=&quot;rGHo&quot;&gt;Добавляем лог:&lt;/p&gt;
  &lt;pre id=&quot;oe7F&quot; data-lang=&quot;kotlin&quot;&gt;private fun fetchDataCoroutines() {    
...
   viewModelScope.launch(exceptionHandler) {        
      ...   
      Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;Current thread: ${Thread.currentThread()};\nisMainThread: ${Looper.getMainLooper().thread == Thread.currentThread()}&amp;quot;)    
   }
}&lt;/pre&gt;
  &lt;p id=&quot;eiCw&quot;&gt;И после этого видим в консоли:&lt;/p&gt;
  &lt;pre id=&quot;RWsW&quot;&gt;MainViewModelDebug: Current thread: Thread[main,5,main];
isMainThread: true&lt;/pre&gt;
  &lt;p id=&quot;tutQ&quot;&gt;И вот она та самая легковесность, о какой сообщалось в самом начале заметки в описании корутин. Не смотря на то, что мы явно не давали указание о том, что запрос делать нужно не в Main-потоке, корутины с помощью подкапотной магии не вывалились в Exception.&lt;/p&gt;
  &lt;p id=&quot;1EZj&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;TOJi&quot; data-align=&quot;center&quot;&gt;Акт девятый: дергаем API через Coroutines, но теперь корректно&lt;/h3&gt;
  &lt;p id=&quot;lapk&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;QJIk&quot;&gt;Не смотря на то, что Exception не произошел - работать с корутинами нужно правильно. И, как мы уже знаем, нужно сделать так, чтобы корутина поняла, что мы хотим выполнить операцию не через главный поток. Для удобства сделаем это, как и в случае с RxJava2, на уровне DataSource и посмотрим на результат.&lt;/p&gt;
  &lt;p id=&quot;06ZO&quot;&gt;Вносим изменения в DataSource в getFactsCoroutines():&lt;/p&gt;
  &lt;pre id=&quot;Rcax&quot; data-lang=&quot;kotlin&quot;&gt;suspend fun getFactsCoroutines() : List&amp;lt;Fact&amp;gt; {
    return withContext(Dispatchers.IO) {
       Log.d(&amp;quot;MainViewModelDebug&amp;quot;, &amp;quot;DataSource: Current thread: ${Thread.currentThread()};\nisMainThread: ${Looper.getMainLooper().thread == Thread.currentThread()}&amp;quot;)        
       apiCoroutines.getAllFactsCoroutines()    
   }
}&lt;/pre&gt;
  &lt;p id=&quot;QA76&quot;&gt;Смотрим логи:&lt;/p&gt;
  &lt;pre id=&quot;0GUJ&quot;&gt;MainViewModelDebug: DataSource: Current thread: Thread[DefaultDispatcher-worker-1,5,main];
isMainThread: false
 
MainViewModelDebug: Success: [Fact(fact=All dogs can be traced...
 
MainViewModelDebug: Current thread: Thread[main,5,main];
isMainThread: true&lt;/pre&gt;
  &lt;p id=&quot;jJyy&quot;&gt;Результат говорит о том, что на уровне DataSource операция выполнилась не в главном потоке, что нам как раз и нужно, а на уровне ViewModel&amp;#x27;и мы уже оказываемся в Main-потоке.&lt;/p&gt;
  &lt;p id=&quot;dDAB&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;SllA&quot; data-align=&quot;center&quot;&gt;Выводы&lt;/h2&gt;
  &lt;p id=&quot;MEpW&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;HjDs&quot;&gt;Что RxJava2 и что Kotlin Coroutines - две мощных библиотеки, позволяющие выполнять асинхронные операции, но с совершенно разными подходами по стилю написания. Оба инструмента помогают Android-разработчикам не грузить жизненноважный Main-thread, что занят и без того нелегкой отрисовкой UI. Kotlin Coroutines все больше набирает обороты и завоевывает новых сторонников из числа разработчиков в свои ряды, тем более на ее стороне легковесность, что позволила в данном примере не получить ошибку при выполнении сетевого запроса, как было в случае с RxJava2.&lt;/p&gt;
  &lt;p id=&quot;x3jI&quot;&gt;При всем при этом нельзя сказать, что век RxJava подошел к концу из-за атаки Корутин и завоевание почти 100% рынка проектов не за горами. У данной библиотеки останется немалое количество поклонников, да и самое главное, что всем нам долго никуда не деться от легаси-кода. Кроме того, на Ютубе и в подкастах, но не помню где точно - слышал мнение, что люди поработали с корутинами, но подход RxJava остался больше по душе.&lt;/p&gt;

</content></entry><entry><id>noobodroid:Ys10aJyt55d</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/Ys10aJyt55d?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>NooboDroid-навигация</title><published>2021-08-01T23:59:26.786Z</published><updated>2021-09-03T15:46:00.443Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/9d/8b/9d8b27eb-8258-4734-b1a6-0382b81a618c.png"></media:thumbnail><summary type="html">Оглавление блога. Все заметки разбиты на категории с кликабельными ссылками.</summary><content type="html">
  &lt;p id=&quot;vIVO&quot;&gt;Оглавление блога. Все заметки разбиты на категории с кликабельными ссылками.&lt;/p&gt;
  &lt;p data-align=&quot;right&quot; id=&quot;aH8m&quot;&gt;&lt;em&gt;Дата запуска блога: 22 июля 2021&lt;/em&gt;&lt;/p&gt;
  &lt;p data-align=&quot;center&quot; id=&quot;ywqw&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 data-align=&quot;center&quot; id=&quot;2AUg&quot;&gt;Android&lt;/h2&gt;
    &lt;h3 id=&quot;MKvV&quot;&gt;1. &lt;a href=&quot;https://teletype.in/@noobodroid/Y4phtRZgdwy&quot; target=&quot;_blank&quot;&gt;Зачем нужны и как понять эти ваши архитектуры в Android?&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;XDZL&quot;&gt;2. &lt;a href=&quot;https://teletype.in/@noobodroid/joA7LpCuhQ-&quot; target=&quot;_blank&quot;&gt;Как развивалась работа с кнопкой в Android?&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;VEfu&quot;&gt;3. &lt;a href=&quot;https://teletype.in/@noobodroid/hgt--QlAUXL&quot; target=&quot;_blank&quot;&gt;Android-NoobLabs: RxJava2 и Kotlin Coroutines&lt;/a&gt;&lt;/h3&gt;
  &lt;/section&gt;
  &lt;p id=&quot;bGU7&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 data-align=&quot;center&quot; id=&quot;PJhz&quot;&gt;Общее&lt;/h2&gt;
    &lt;h3 id=&quot;47AN&quot;&gt;1. &lt;a href=&quot;https://teletype.in/@noobodroid/HZ0OCYtAUZv&quot; target=&quot;_blank&quot;&gt;ООП. От создания до сегодняшних дней&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;piYY&quot;&gt;2. &lt;a href=&quot;https://teletype.in/@noobodroid/hT5MmoXjJvn&quot; target=&quot;_blank&quot;&gt;Полиморфизм и его виды&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;Lb6m&quot;&gt;3. &lt;a href=&quot;https://teletype.in/@noobodroid/7N_Q6lhaolx&quot; target=&quot;_blank&quot;&gt;Немного про сложность алгоритмов&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;orxF&quot;&gt;4. &lt;a href=&quot;https://teletype.in/@noobodroid/QGepGDWvM-T&quot; target=&quot;_blank&quot;&gt;Зачем мне эти ваши структуры данных?&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;Oidj&quot;&gt;5. &lt;a href=&quot;https://teletype.in/@noobodroid/7AoQoWax7QC&quot; target=&quot;_blank&quot;&gt;BCS (Base Computer Science): Оглавление&lt;/a&gt;&lt;/h3&gt;
  &lt;/section&gt;
  &lt;p id=&quot;hkw5&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 data-align=&quot;center&quot; id=&quot;WlXF&quot;&gt;Поиск работы и резюме&lt;/h2&gt;
    &lt;h3 id=&quot;9YX9&quot;&gt;1. &lt;a href=&quot;https://teletype.in/@noobodroid/TrV8_eiiHr7&quot; target=&quot;_blank&quot;&gt;Тернистый путь до Android-разработчика&lt;/a&gt; (моя история трудоустройства)&lt;/h3&gt;
    &lt;h3 id=&quot;Pvmf&quot;&gt;2. &lt;a href=&quot;https://teletype.in/@noobodroid/ggvxWdNuI61&quot; target=&quot;_blank&quot;&gt;Вопросы junior-IT-шника работодателю&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;KUPj&quot;&gt;3. &lt;a href=&quot;https://teletype.in/@noobodroid/N_UTN-u5hxW&quot; target=&quot;_blank&quot;&gt;Как IT-новичку победить процесс найма. Резюме&lt;/a&gt;&lt;/h3&gt;
  &lt;/section&gt;
  &lt;p id=&quot;omQo&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 data-align=&quot;center&quot; id=&quot;nwVt&quot;&gt;Полезные подборки&lt;/h2&gt;
    &lt;h3 id=&quot;VtGV&quot;&gt;1. &lt;a href=&quot;https://teletype.in/@noobodroid/xDKUOUjZOVD&quot; target=&quot;_blank&quot;&gt;Что читать в Telegram по мобильной разработке?&lt;/a&gt;&lt;/h3&gt;
    &lt;h3 id=&quot;OOCI&quot;&gt;2. &lt;a href=&quot;https://teletype.in/@noobodroid/ooX6Ui0L9sK&quot; target=&quot;_blank&quot;&gt;Мобильная разработка: YouTube-каналы и подкасты на русском языке&lt;/a&gt;&lt;/h3&gt;
  &lt;/section&gt;

</content></entry><entry><id>noobodroid:ooX6Ui0L9sK</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/ooX6Ui0L9sK?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Мобильная разработка: YouTube-каналы и подкасты на русском языке</title><published>2021-08-01T23:22:03.345Z</published><updated>2021-08-02T17:58:04.243Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/84/14/84142b16-be7a-4868-bcc1-f9278370b23e.jpeg"></media:thumbnail><category term="mobil-naya-razrabotka" label="Мобильная разработка"></category><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/9f/cc/9fcc6726-c5b7-41d9-a497-4fcaad9bb1b1.jpeg&quot;&gt;В данной заметке предлагаю подборку каналов и подкастов по мобильной разработке. Каналы будут упорядочены по порядку убывания подписчиков. Начну с подкастов. Кроме этого, уже есть заметка со списком телеграм-каналов по мобильной разработке.</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/9f/cc/9fcc6726-c5b7-41d9-a497-4fcaad9bb1b1.jpeg&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;В данной заметке предлагаю подборку каналов и подкастов по мобильной разработке. Каналы будут упорядочены по порядку убывания подписчиков. Начну с подкастов. Кроме этого, уже есть &lt;a href=&quot;https://teletype.in/@noobodroid/xDKUOUjZOVD&quot; target=&quot;_blank&quot;&gt;заметка&lt;/a&gt; со списком телеграм-каналов по мобильной разработке.&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h2 data-align=&quot;center&quot;&gt;Подкасты&lt;/h2&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;&lt;strong&gt;1. Mobile People Talks&lt;/strong&gt;&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img2.teletype.in/files/d2/ba/d2ba1fb8-ef69-4fc4-bf6d-687f8ac2a28e.jpeg&quot; width=&quot;225&quot; /&gt;
      &lt;figcaption&gt;&lt;strong&gt;Mobile People Talks&lt;/strong&gt;&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное описание подкаста:&lt;/strong&gt; Mobile People Talks — подкаст про мобильную разработку. И все остальное. Так что если вы не мобильный разработчик, не спешите закрывать страничку – разные выпуски имеют разные уровни погружения и будут интересны разработчикам с разным стажем и степенью мобильности). Хочется надеяться, что подкаст станет регулярным ресурсом, который поможет вам создавать лучшие приложения и продвигать их более эффективно, так как всегда есть место для роста экспертизы в мобильной разработке, учитывая сложный характер этой отрасли.&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;Ссылки подкасты:&lt;/strong&gt; &lt;a href=&quot;https://podcasts.apple.com/ru/podcast/mobile-people-talks/id1457942497&quot; target=&quot;_blank&quot;&gt;apple&lt;/a&gt;, &lt;a href=&quot;https://podcasts.google.com/feed/aHR0cHM6Ly9mZWVkcy5zb3VuZGNsb3VkLmNvbS91c2Vycy9zb3VuZGNsb3VkOnVzZXJzOjYwNzU5Mzg4Mi9zb3VuZHMucnNz&quot; target=&quot;_blank&quot;&gt;google&lt;/a&gt; и &lt;a href=&quot;https://soundcloud.com/mobilepeopletalks&quot; target=&quot;_blank&quot;&gt;soundCloud&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;2. Android story&lt;/h3&gt;
    &lt;figure class=&quot;m_retina&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img2.teletype.in/files/11/0e/110e1daf-5373-4655-aa12-40cd881873db.jpeg&quot; width=&quot;300&quot; /&gt;
      &lt;figcaption&gt;Android story&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное описание подкаста:&lt;/strong&gt; Двое андроидщиков, двое Вов и иногда два разных мнения. Каждый подкаст мы обсуждаем новые статьи и просто новинки в мире андроида и программирования. Делимся мнениями, опытом и иногда пытаемся несмешно шутить.&lt;/p&gt;
    &lt;p&gt;Подкаст, соответственно, ведут, аккаунты в твиттере: &lt;a href=&quot;https://twitter.com/smallstells&quot; target=&quot;_blank&quot;&gt;Володимир Стельмащук&lt;/a&gt; и &lt;a href=&quot;https://twitter.com/phoenixxt/with_replies&quot; target=&quot;_blank&quot;&gt;Вова.&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://androidstory.buzzsprout.com/&quot; target=&quot;_blank&quot;&gt;Ссылка на страницу&lt;/a&gt; с доступными площадками подкастов&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UC6-NFk4uOGsKvyisL1QC3rw&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h2 data-align=&quot;center&quot;&gt;YouTube&lt;/h2&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;1. Start Android&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/21/76/2176388d-6022-43fd-b258-7fe2643ea1c9.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Start Android&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;Обучающие видео-уроки по разработке приложений и игр для Android. Подпишитесь на наш канал, чтобы не пропустить новые уроки - обновление еженедельно! Мы поможем любому новичку стать продвинутым разработчиком андроид-приложений!&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCzE7HcbvyEiS5ea1rVRbPLQ&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(34,  84%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;2. Mobile Developer&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/c6/38/c6381747-0ec1-493e-a4fb-52cc7c3c242d.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Mobile Developer&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;Всем привет! Меня зовут Алексей. Если ты когда-нибудь задумывался о том, чтобы делать крутые приложения для телефонов, хотел сделать свой инстаграмм или фейсбук, то тебе сюда. Свежие видео, новости из мира разработки, интервью и многое другое здесь - на канале Mobile Developer&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://twitter.com/NeuraSC2&quot; target=&quot;_blank&quot;&gt;Twitter автора&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/mobiledevnews&quot; target=&quot;_blank&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCxGXkPks1Ykbx2Plt4DgZlA&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(34,  84%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;3. Android Broadcast. Все об Андроид разработке&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img4.teletype.in/files/74/06/74066f4f-a78d-46e6-8a7c-fc4bda899611.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Android Broadcast&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;Всё о современной разработке под Android от экспертов индустрии На канале вы найдёте: - Разбор свежих новинок из мира Android и мобильной разработки - Лучшие практики Android разработки - Интервью с ведущими экспертами индустрии - Тестовые собеседования в прямом эфире с разбором&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://twitter.com/andro_broadcast&quot; target=&quot;_blank&quot;&gt;Twitter проекта&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://twitter.com/kirill_rozov&quot; target=&quot;_blank&quot;&gt;Twitter автора&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/android_broadcast&quot; target=&quot;_blank&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCKsqMPIIhev3qbMxCL8Emvw&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;4. Mobius&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img4.teletype.in/files/fd/fc/fdfc14e3-2678-4f2c-b99e-80e61196fbb0.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Mobius&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;На этом канале публикуются видео с Mobius — конференции для разработчиков под Android и iOS. Наверняка вы уже бывали на конференциях по мобильной разработке и знаете, что это такое... Теперь представьте, что из них аккуратно вырезали всю маркетинговую лапшу, «продающие» доклады и полностью сосредоточились на хардкоре и чистой практике. Вы получите Mobius — главную независимую конференцию по мобильной разработке в России!&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://twitter.com/MobiusConf&quot; target=&quot;_blank&quot;&gt;Twitter проекта&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/mobiusconf&quot; target=&quot;_blank&quot;&gt;Telegram-чат&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCG70q1HRspLdd93HW94WS-A&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;5. Mobile Channel&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/a4/99/a4996c0a-707c-438e-a16b-05688b01ff73.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Mobile Channel&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала:  &lt;/strong&gt;Контент Mobile Channel посвящен разработке мобильных приложений: технологиям Android и iOS, кросс-платформенной разработке, архитектуре мобильных приложений, клиент-серверному взаимодействию и процессам разработки и тестирования. Здесь мы публикуем материалы с профессиональной конференции для мобильных разработчиков AppsConf (&lt;a href=&quot;http://appsconf.ru/&quot; target=&quot;_blank&quot;&gt;http://appsconf.ru/&lt;/a&gt;).&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://twitter.com/AppsConfRussia&quot; target=&quot;_blank&quot;&gt;Twitter проекта&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCP8MtCo2ZcrJc7_Zhcjym9g&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;6. Mobile People&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/a6/44/a644dab2-3771-4716-b92b-ea4e1cad1903.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Mobile People&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала:  -&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/mobile_people&quot; target=&quot;_blank&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCSzaLrrKbo8M2gJGulavIkA&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(199, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;7. Android Guards&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/4c/1e/4c1e2ce7-660f-4304-9134-36e718b12fed.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Android Guards&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;Официальный канал сообщества Android Guards.&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/android_guards_today&quot; target=&quot;_blank&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCSzaLrrKbo8M2gJGulavIkA&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3&gt;8. Android Live&lt;/h3&gt;
    &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/c1/dd/c1ddd151-9d34-4dd2-90ec-ecc5c59952cd.jpeg&quot; width=&quot;88&quot; /&gt;
      &lt;figcaption&gt;Android Live&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;p&gt;&lt;strong&gt;Основное писание канала: &lt;/strong&gt;Всем привет. На данном канале вы найдёте самые актуальные новости из мира Android-разработки. Как подготавливаться к собеседованиям? Какие технологии изучать, чтобы оставаться в тренде? Это и многое другое можно узнать на канале Android Live.&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://t.me/android_live&quot; target=&quot;_blank&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UC1BmHcuVShCt3Rb1eENbiAA&quot; target=&quot;_blank&quot;&gt;YouTube-канал&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;

</content></entry><entry><id>noobodroid:AjF3wPU_7k2</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/AjF3wPU_7k2?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>BCS: Потоки и процессы</title><published>2021-08-01T10:03:53.269Z</published><updated>2021-08-01T10:22:25.159Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/a3/d7/a3d7ff03-b749-4164-8af3-e7715eb9b849.jpeg"></media:thumbnail><category term="computer-science" label="Computer Science"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/ab/65/ab65dfea-e379-45a0-8ec0-00609f1224cf.jpeg&quot;&gt;Процесс - совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированны друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие может осуществляться только с помощью специальных средств). Для каждого процесса ОС создает &quot;виртуальное адресное пространство&quot;, к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система отвечает за то, как виртуальное пространство процессов проецируется на физическую память. Резюмируя, процесс - понятие на уровне операционной системы.</summary><content type="html">
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ab/65/ab65dfea-e379-45a0-8ec0-00609f1224cf.jpeg&quot; width=&quot;640&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;Процесс&lt;/strong&gt; - совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированны друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие может осуществляться только с помощью специальных средств). Для каждого процесса ОС создает &amp;quot;виртуальное адресное пространство&amp;quot;, к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система отвечает за то, как виртуальное пространство процессов проецируется на физическую память. Резюмируя, процесс - понятие на уровне операционной системы.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Поток&lt;/strong&gt; - использует выделенные для процесса ресурсы и является способом выполнения процесса. Главный поток выполняет main-функцию и завершается. При выполнении главного потока могут порождаться дополнительные потоки. Потоки одного процесса могут обмениваться данными между собой.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Поток-демон&lt;/strong&gt; - поток работающий в фоновом режиме. Если все потоки не демоны закончили свою работу, то программа завершается, не смотря на работу потоков-демонов.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Монитор&lt;/strong&gt; - дополнительная надстройка над mutex&amp;#x27;ом, в Java реализуется с помощью  ключевого слова synchronized.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Семафор&lt;/strong&gt; - средство для синхронизации доступа к какому-либо ресурсу. Особенность в том, что при создании механизма синхронизации он использует считчик, который указывает сколько потоков одновременно могут получать доступ к общему ресурсу. Семафоры в Java представлены специальным классом Semaphore.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Mutex&lt;/strong&gt; - специальный объект для синхронизации потоков, прикреплен к каждому объекту Java, поэтому есть у всех экземпляров класса. Mutex - одноместный семафор.&lt;/p&gt;
  &lt;h2&gt;&lt;strong&gt;*ЗАМЕТКА НА СТАДИИ РАЗРАБОТКИ*&lt;/strong&gt;&lt;/h2&gt;

</content></entry><entry><id>noobodroid:-iLe27Y5qLz</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/-iLe27Y5qLz?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>BCS: Сеть</title><published>2021-08-01T09:57:46.619Z</published><updated>2021-08-02T14:31:28.881Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/35/86/3586325a-6231-4ab4-a5fd-36f56ed65cfd.jpeg"></media:thumbnail><category term="computer-science" label="Computer Science"></category><summary type="html">&lt;img src=&quot;https://img4.teletype.in/files/7b/12/7b121103-ce3b-4b19-98bb-904ad960d390.jpeg&quot;&gt;BCS - Base Computer Science. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.</summary><content type="html">
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/7b/12/7b121103-ce3b-4b19-98bb-904ad960d390.jpeg&quot; width=&quot;652&quot; /&gt;
  &lt;/figure&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p&gt;&lt;strong&gt;BCS - Base Computer Science&lt;/strong&gt;. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 data-align=&quot;center&quot;&gt;Общие определения&lt;/h2&gt;
  &lt;p&gt;&lt;strong&gt;Сетевой протокол&lt;/strong&gt; - стандарт передачи и обработки информации. Кроме сетевых протоколов бывают и почтовые протоколы (SMTP, POP, IMAP и др), протоколы передачи файлов (FTP) и другие.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;IP и TCP&lt;/strong&gt; - два разных протокола, которые связывают друг с другом. Часто употребляются в комбинации сразу нескольких протоколов, каждый из которых выполняет операции на своем уровне.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;TCP&lt;/strong&gt; - отвечает за создание интернет-пакетов и их обратную сборку в нужном порядке в месте получения, а так же проверяет целостность информации.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;IP&lt;/strong&gt; - используется для доставки по нужному адресу, каждый отправленный пакет содержит адрес доставки, отвечает за маршрутизацию пакета к указанному компьютеру.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;UDP&lt;/strong&gt; - для передачи малых кусков информации, не гарантирует доставку пакетов в нужной последовательности и не дублирует передачу утерянных пакетов, но выше скорость передачи и меньше потребление системных ресурсов.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Socket&lt;/strong&gt; - это программный интерфейс. Это абстрактное понятие, которое, в большинстве случаев, используется для коммуникации программ в сети (но не только).&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;WebSocket&lt;/strong&gt; - это протокол (какой-либо заранее оговоренный порядок) обмена данными (как, например, http, ftp, ssl и т.д.). Этот протокол идет поверх (передается посредством) протокола TCP.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;SSL (Secure Sockets Layer) - &lt;/strong&gt;тип цифровой безопасности, которая позволяет зашифровать связь между веб-сайтом и веб-браузером.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;TLS (Transport Layer Security)&lt;/strong&gt; - обеспечивает конфиденциальность данных так же, как и SSL.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;SSL/TLS handshake &lt;/strong&gt;- ряд шагов, благодаря которому клиент и сервер инцируют связб, проверяют друг друга и начинают передачу данных через туннель SSL/TLS.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;REST (REpresentational State Transfer)&lt;/strong&gt; - термин, который первоначально введен Роем Филдингом (Roy Fielding), кто являлся одним из создателей протокола HTTP. Отличительной особенностью сервисов REST является то, что они позволяют наилучшим образом использовать протокол HTTP.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt; - синтаксис, который описывает как запрашивать данные, и, в основном, используется клиентом для загрузки данных с сервера. Один из подходов проектирования API, альтернатива REST.&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h2 data-align=&quot;center&quot;&gt;HTTP&lt;/h2&gt;
  &lt;p&gt;&lt;strong&gt;HTTP-протокол&lt;/strong&gt; - пользователь иницирует соединение к серверу для запроса информации, а сервер ожидает соединение для получения запроса, обрабатывает запрос и возвращает обратно сообщение с результатом. Работает совместно с протоколом TCP.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;HTTPS&lt;/strong&gt; - безопасное расширение HTTP устанавливающие и настраивающие SSL/TLS-сертификат&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Метод HTTP &lt;/strong&gt;— указывает на основную операцию над ресурсом. Методы бывают (подробнее о методах позже, после идемпотентности):&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;GET&lt;/li&gt;
    &lt;li&gt;POST&lt;/li&gt;
    &lt;li&gt;HEAD&lt;/li&gt;
    &lt;li&gt;OPTIONS&lt;/li&gt;
    &lt;li&gt;PUT&lt;/li&gt;
    &lt;li&gt;PATCH&lt;/li&gt;
    &lt;li&gt;DELETE&lt;/li&gt;
    &lt;li&gt;TRACE&lt;/li&gt;
    &lt;li&gt;CONNECT&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;strong&gt;Коды состояния&lt;/strong&gt; бывают:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;1xx - Informational&lt;/li&gt;
    &lt;li&gt;2xx - Success&lt;/li&gt;
    &lt;li&gt;3xx - Redirection&lt;/li&gt;
    &lt;li&gt;4xx - Client error&lt;/li&gt;
    &lt;li&gt;5xx - Server error&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h3 data-align=&quot;center&quot;&gt;&lt;strong&gt;Структура HTTP-сообщения&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;&lt;strong&gt;1. Стартовая строка (Starting line) &lt;/strong&gt;определяет тип сообщения&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Для запроса: Метод URI HTTP/Версия&lt;/li&gt;
    &lt;li&gt;Для ответа: HTTP/Версия Код состояние Пояснение&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;strong&gt;2. Заголовки (Headers)&lt;/strong&gt; - тело сообщения, параметры передачи и прочее. Виды заголовком в порядке рекомендованной очередности посыла:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;General headers - могут включаться в любое сообщение клиента и сервера;&lt;/li&gt;
    &lt;li&gt;Request headers - используются только в запросах клиента;&lt;/li&gt;
    &lt;li&gt;Response headers - только для ответов от сервера;&lt;/li&gt;
    &lt;li&gt;Entity headers - сопровождают каждую сущность сообщения.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;strong&gt;3. Тело сообщения&lt;/strong&gt; &lt;strong&gt;(Message Body)&lt;/strong&gt; - отделяется от заголовка пустой строкой, это непосредственно данные сообщения&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h3 data-align=&quot;center&quot;&gt;Идемпотентность, безопасность и методы HTTP&lt;/h3&gt;
  &lt;p&gt;&lt;strong&gt;Идемпотентность&lt;/strong&gt; - свойство объекта или операции при повторном ее применении к объекту давать тот же результат, что и при первом. То есть идемпотентная операция - действие, многократное повторение которого эквивалетно однократному.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Безопасный HTTP-метод&lt;/strong&gt; - метод не меняющий состояние сервера.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Идемпотентный и небезопасный метод&lt;/strong&gt; - сколько бы не повторялся запрос, только первый изменит состояние системы, а остальные состояние системы &lt;strong&gt;не меняют&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Идемпотентный и безопасный метод&lt;/strong&gt; - многократное повторение запроса вернет одно и то же состояние системы&lt;/p&gt;
  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Самое использование HTTP-методов при проектировании Rest-API - НЕ ГАРАНТИРУЕТ идемпотентность, разработчик легко может ее нарушить.&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
  &lt;p&gt;Теперь конкретно по основным характеристикам методов:&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;1. CONNECT&lt;/strong&gt; - запускает двустороннюю связь с запрошенным ресурсом, можно использовать для открытия туннеля&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4d/f3/4df3e7ce-7ddc-41a8-af07-fa455c8cd3c3.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;2. HEAD &lt;/strong&gt;- запрашивает заголовки. Такой запрос может быть выполнен перед загрузкой большого ресурса, например, для экономии пропускной способности.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/46/fa/46fabb66-7542-4226-8887-5e017314ae77.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;3. TRACE&lt;/strong&gt; - выполняет проверку обратной связи по пути к целевому ресурсу, предоставляя полезный механизм отладки.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/11/71/11715e03-8132-4b32-9e37-9d04fed93b21.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;4. OPTIONS&lt;/strong&gt; -используется для описания параметров соединения с целевым ресурсом.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/2b/34/2b344998-285f-4d3d-84ae-d4c0c5217905.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;5. GET&lt;/strong&gt; - запрашивает представление указанного ресурса, запросы должны только получать данные. &lt;strong&gt;ВАЖНО: &lt;/strong&gt;GET-запрос имеет ограниченную длину&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f0/6b/f06bfc7e-8340-40a3-8fb4-503da69a0b8a.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;6. POST&lt;/strong&gt; - предназначен для отправки данных на сервер. Тип тела запроса указывается в заголовке Content-type. &lt;strong&gt;ВАЖНО:&lt;/strong&gt; в отличие от GET - метод POST не имеет ограничений по длине и соответственно не вызовет ошибку и условно не кэшируется.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d7/48/d748d3c7-d19e-4dba-b5cc-fd71b9ec4133.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;7. PUT&lt;/strong&gt; - создаёт новый ресурс или заменяет представление целевого ресурса, данными представленными в теле запроса. &lt;strong&gt;ВАЖНО: &lt;/strong&gt;PUT в отличие от POST является идемпотентным&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/97/4b/974b278c-9f76-447d-b24a-13a68900f5d6.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;8. PATCH&lt;/strong&gt; - имеет поведение типичного update-метода в CRUD&amp;#x27;ах. &lt;strong&gt;ВАЖНО: &lt;/strong&gt;PATCHможет как быть идемпотентным, так и нет, в отличие от PUT, который всегда идемпотентен.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/fd/31/fd31053a-349e-42b6-a104-a5f01993e0e9.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;9. DELETE&lt;/strong&gt; -  удаляет указанный ресурс. &lt;strong&gt;ВАЖНО: &lt;/strong&gt;корректно реализованный DELETE является идемпотентным.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b3/c1/b3c17119-dc5b-458f-95d6-bec58942d33f.png&quot; width=&quot;791&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;В основном материал брался:&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://ru.wikipedia.org/wiki/HTTP&quot; target=&quot;_blank&quot;&gt;https://ru.wikipedia.org/wiki/HTTP&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ru/docs/Web/HTTP/Methods/CONNECT&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ru/docs/Web/HTTP/Methods/CONNECT&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>noobodroid:7AoQoWax7QC</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/7AoQoWax7QC?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>BCS: Оглавление</title><published>2021-08-01T09:52:12.399Z</published><updated>2021-08-01T10:21:48.376Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/23/c6/23c664ad-437a-4871-8b6a-318ac5454047.jpeg"></media:thumbnail><category term="computer-science" label="Computer Science"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/6b/93/6b93ab64-7495-4afd-ae65-7cf96110492e.jpeg&quot;&gt;BCS - Base Computer Science. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/6b/93/6b93ab64-7495-4afd-ae65-7cf96110492e.jpeg&quot; width=&quot;1500&quot; /&gt;
  &lt;/figure&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p&gt;&lt;strong&gt;BCS - Base Computer Science&lt;/strong&gt;. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2&gt;1. &lt;a href=&quot;https://teletype.in/@noobodroid/AjF3wPU_7k2&quot; target=&quot;_blank&quot;&gt;Процессы и потоки&lt;/a&gt;&lt;/h2&gt;
  &lt;h2&gt;2. &lt;a href=&quot;https://teletype.in/@noobodroid/-iLe27Y5qLz&quot; target=&quot;_blank&quot;&gt;Сеть&lt;/a&gt;&lt;/h2&gt;
  &lt;h2&gt;*ЗАМЕТКА НА СТАДИИ РАЗРАБОТКИ*&lt;/h2&gt;

</content></entry><entry><id>noobodroid:joA7LpCuhQ-</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/joA7LpCuhQ-?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Как развивалась работа с кнопкой в Android?</title><published>2021-07-30T17:35:27.523Z</published><updated>2021-08-02T20:26:32.887Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/af/ef/afefbbf8-eb59-4326-bd94-2abc3e5270b9.jpeg"></media:thumbnail><category term="android" label="Android"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/a9/e6/a9e6a4fe-5e04-4db0-9bdb-36c2227c0b99.jpeg&quot;&gt;На днях вышел Jetpack Compose, поэтому решил ностальгически пройтись по тем способам работы с View-слоем, какие были популярны у Android-разработчиков ранее, потому что работа с XML на View-слое уходит в прошлое.</summary><content type="html">
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;figure class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/a9/e6/a9e6a4fe-5e04-4db0-9bdb-36c2227c0b99.jpeg&quot; width=&quot;418&quot; /&gt;
      &lt;figcaption&gt;Кнопки мои кнопки&lt;/figcaption&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;p&gt;На днях вышел Jetpack Compose, поэтому решил ностальгически пройтись по тем способам работы с View-слоем, какие были популярны у Android-разработчиков ранее, потому что работа с XML на View-слое уходит в прошлое.&lt;/p&gt;
  &lt;h2&gt;0. Способы &amp;quot;из коробки&amp;quot;&lt;/h2&gt;
  &lt;h3&gt;0.1 findViewById&lt;/h3&gt;
  &lt;p&gt;findViewById - нативный вариант работы с кнопкой. Итак, у нас есть в XML какая-то кнопка. Чтобы работать с ней из Java или Kotlin кода - нужно в XML задать ей ID:&lt;/p&gt;
  &lt;pre data-lang=&quot;xml&quot;&gt; ...
 &amp;lt;Button
    android:id=&amp;quot;@+id/button&amp;quot;
    android:text=&amp;quot;Button&amp;quot;
    ... /&amp;gt;
...&lt;/pre&gt;
  &lt;p&gt;При компиляции приложения aapt создаст класс R, который содержит ресурс IDs для всех ресурсов в каталоге res.&lt;/p&gt;
  &lt;p&gt;Как правило, с кнопкой нужно работать не в одном каком-то методе жизненного цикла, но и обращаться к ней из класса бизнес-логики, то есть Presenter&amp;#x27;а или ViewModel&amp;#x27;и и нужно, чтобы кнопка была объявлена полем, заодно повесим слушать кликов что примерно будет выглядеть так:&lt;/p&gt;
  &lt;pre data-lang=&quot;java&quot;&gt;public class MainActivity extends AppCompatActivity {
  
   Button button;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.nd_activity_main);
      button = (Button) findViewById(R.id.button);
      button.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            onClickButtons(v)
         }
      });
   }
   
   void onClickButtons(View view) {
      Toast.makeText(
      this, 
      &amp;quot;Здесь обработка клика&amp;quot;, 
      Toast.LENGTH_SHORT).show();
   }
}&lt;/pre&gt;
  &lt;h3&gt;0.2 onClick в XML&lt;/h3&gt;
  &lt;p&gt;Этот добавился несколько позже и позволяет задать вызов метода из XML-разметки напрямую. И данный способ не работает во фрагментах, только в Activity. Выглядит это так:&lt;/p&gt;
  &lt;pre data-lang=&quot;xml&quot;&gt; ...
 &amp;lt;Button
    android:id=&amp;quot;@+id/button&amp;quot;
    android:text=&amp;quot;Button&amp;quot;
    android:onClick=&amp;quot;onClickButtons&amp;quot;
    ... /&amp;gt;
 ...&lt;/pre&gt;
  &lt;pre data-lang=&quot;java&quot;&gt;public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
   
   void onClickButtons(View view) {
      Toast.makeText(
      this, 
      &amp;quot;Здесь обработка клика&amp;quot;, 
      Toast.LENGTH_SHORT).show();
   }
}&lt;/pre&gt;
  &lt;h3&gt;0.3 OnClickListener&lt;/h3&gt;
  &lt;p&gt;Здесь нужно было просто реализовать интерфейс в Activity или Fragment&amp;#x27;е, что на в итоге приводит к такому:&lt;/p&gt;
  &lt;pre data-lang=&quot;java&quot;&gt;public class MainActivity extends AppCompatActivity 
implements View.OnClickListener {
 
   Button button;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.nd_activity_main);
      button = (Button) findViewById(R.id.button);
      button.setOnClickListener(this);
   }
   
   @Override
   public void onClick(View v) {
      onClickButtons()
   }
   
   void onClickButtons(View view) {
      Toast.makeText(
      this, 
      &amp;quot;Здесь обработка клика&amp;quot;, 
      Toast.LENGTH_SHORT).show();
   }
}&lt;/pre&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;2. ButterKnife&lt;/h2&gt;
  &lt;p&gt;Разработчики - люди ленивые. И им изначально казалось, что совершается слишком много телодвижений для начала работы со виджетом. И большую популярность обрела библиотека &lt;a href=&quot;https://github.com/JakeWharton/butterknife&quot; target=&quot;_blank&quot;&gt;ButterKnife&lt;/a&gt;, которую написал &lt;a href=&quot;https://itsobes.ru/AndroidSobes/kto-takoj-dzhejk-vorton/&quot; target=&quot;_blank&quot;&gt;Jake Wharton.&lt;/a&gt; Первая версия библиотеки вышла 5 марта 2013 года. Как выглядел тот же самый, но чуть расширенный код относительно того, что выше (пример позволяет обрабатывать клик двух кнопок):&lt;/p&gt;
  &lt;pre data-lang=&quot;java&quot;&gt;public class MainActivity extends AppCompatActivity {
  
   @BindView(R.id.button)
   Button button;
   
   @BindView(R.id.button2)
   Button button2;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      ButterKnife.bind(this);
   }
   
   @OnClick({R.id.button, R.id.button2})
   void onClickButtons(View view) {
      switch (view.getId()) {
         case R.id.button:
         Toast.makeText(this,
         &amp;quot;Здесь обработка клика button&amp;quot;,
         Toast.LENGTH_SHORT).show();
         break;
         
         case R.id.button2:
         Toast.makeText(
         this, 
         &amp;quot;Здесь обработка клика button2&amp;quot;,
         Toast.LENGTH_SHORT).show();
         break;
      }
   }
}&lt;/pre&gt;
  &lt;h2&gt;&lt;/h2&gt;
  &lt;hr /&gt;
  &lt;h2&gt;3. DataBinding&lt;/h2&gt;
  &lt;p&gt;В 2015 году уже были release-candidate версии этого решения от Google. Точную дату выхода релизной версии не помню, но по-моему активно заговорили о таком решении после Google IO 2017. Нельзя сказать, что оно было очень популярным, так как суть работы происходит через кодогенерацию, что увеличивает время сборки проектов. Это плохо тем, что в сегодняшние дни очень крупные компании стараются модуляризировать свою архитектуру, чтобы при каких-либо изменениях пересобиралась как можно меньшая часть проекта и соответственно уменьшалось время сборки, хотя они даже не используют DataBinding. Сама суть DataBindinga в связывании напрямую xml-кода и ViewModel-класса бизнес-логики, что позволяло даже писать Java-код в XML, то есть у нас напрямую вызывалась функция класса ViewModel&amp;#x27;и через лямбда-выражение:&lt;/p&gt;
  &lt;pre data-lang=&quot;xml&quot;&gt;...
&amp;lt;layout xmlns:android=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;
    xmlns:app=&amp;quot;http://schemas.android.com/apk/res-auto&amp;quot;&amp;gt;
    &amp;lt;data&amp;gt;
    &amp;lt;variable
    name=&amp;quot;viewModel&amp;quot;
    type=&amp;quot;com.example.project.MainViewModel&amp;quot; /&amp;gt;
    ...
 &amp;lt;Button
    android:id=&amp;quot;@+id/button&amp;quot;
    android:text=&amp;quot;Button&amp;quot;
    android:onClick=&amp;quot;@{() -&amp;gt; viewModel.onClickButtons()}&amp;quot;
    ... /&amp;gt;
...&lt;/pre&gt;
  &lt;h2&gt;&lt;/h2&gt;
  &lt;hr /&gt;
  &lt;h2&gt;4. Kotlin Synthetyc&lt;/h2&gt;
  &lt;p&gt;Если верить тому, как мельком я посмотрел доступные GitHub-репозитории, то разработка Kotlin Synthetyc началась примерно примерно в середине 2016 года. Но данный способ работы со View хоть и был немногословным, но быстро стал Deprecated в версии Kotlin 1.4.20, что датирована 5 мая 2021 года. Принцип работы основан на генерации кода плагином, который автоматически подтягивал нужный import.&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot;&gt; 
import kotlinx.android.synthetic.main.activity_main.*
 
class MainActivity: AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.nd_activity_main)
      button.setOnClickListener {
         onClickButtons()
      }
   }
   
   fun onClickButtons() {
      Toast.makeText(
      this, 
      &amp;quot;Здесь обработка клика&amp;quot;, 
      Toast.LENGTH_SHORT).show();
   }
}&lt;/pre&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;5. ViewBinding&lt;/h2&gt;
  &lt;p&gt;В феврале 2020 года с выходом Android Gradle plugin 3.6.0 - разработчики смогли подключать ViewBinding для работы со View в своих проектах. Данный метод тоже основан на генерации binding-классов, но ликвидирован недостаток DataBindinga в виде очень долгого времени сборки, ну и соответственно нет возможности писать код в XML.&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot;&gt;class MainActivity: AppCompatActivity() {

   private lateinit var binding: ActivityMainBinding
   
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      binding = ActivityMainBinding.inflate(layoutInflater)
      setContentView(binding.root)
      binding.button.setOnClickListener {
         onClickButtons()
      }
   }
   
   fun onClickButtons() {
      Toast.makeText(
      this, 
      &amp;quot;Здесь обработка клика&amp;quot;, 
      Toast.LENGTH_SHORT).show();
   }
}&lt;/pre&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2&gt;6. Jetpack compose &lt;/h2&gt;
    &lt;p&gt;28 июля 2021 года - по-настоящему революционная дата для Android-разработчиков. В этот день сменился полностью подход работы со View-слоем приложения. Если во всех вышеназванных способах суть заключалась в различных попытках связать XML-код и Java/Kotlin код, то вышедший в релизной версии Jetpack Compose предлагает декларативную верстку UI прямо в Kotlin-классах. И этот тот подход, какой определенно вытеснит в будущем XML.&lt;/p&gt;
    &lt;pre data-lang=&quot;kotlin&quot;&gt;
class MainActivity : ComponentActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)    
       setContent {
               Example(&amp;quot;Android&amp;quot;)    
       }
   }
}
    
@Composable 
fun Example(name: String) {
   val ctx = LocalContext.current 
   Button(onClick = {

      onClickButtons(ctx,&amp;quot;Здесь обработка клика&amp;quot;)
      
   }, colors = ButtonDefaults.textButtonColors( 
      backgroundColor = Color.Red 
   )) { 
      Text(text = name) 
   } 
}


fun onClickButtons(ctx: Context, msg: String) {    
   Toast.makeText(ctx, msg, Toast.LENGTH_SHORT).show()
}   
&lt;/pre&gt;
  &lt;/section&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/ze-Lp0Xevh4?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;

</content></entry><entry><id>noobodroid:xDKUOUjZOVD</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/xDKUOUjZOVD?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Что читать в Telegram по мобильной разработке?</title><published>2021-07-30T12:06:36.063Z</published><updated>2021-08-02T00:41:20.916Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/b2/74/b274e11c-68f8-4a81-b8f6-c45a5863b6d7.jpeg"></media:thumbnail><category term="mobil-naya-razrabotka" label="Мобильная разработка"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/85/9e/859e7c9a-6cb2-4393-88ab-9bb849869934.jpeg&quot;&gt;Мобильному разработчику важно держать руку на пульсе. На мой взгляд в этом сильно помогает телеграм и несколько крутейших каналов, по каким удобно держаться в тренде. Какие-то каналы буду вносить в список без подводки. Не от того, что они хуже, а от того, что во многом каналы носят информационный характер. Поехали!</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/85/9e/859e7c9a-6cb2-4393-88ab-9bb849869934.jpeg&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Мобильному разработчику важно держать руку на пульсе. На мой взгляд в этом сильно помогает телеграм и несколько крутейших каналов, по каким удобно держаться в тренде. Какие-то каналы буду вносить в список без подводки. Не от того, что они хуже, а от того, что во многом каналы носят информационный характер. Поехали!&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;1. Мобильная разработка&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/10/2e/102e2d7a-2716-4a03-b548-becccae76ac4.png&quot; width=&quot;2276&quot; /&gt;
    &lt;figcaption&gt;Swift, Kotlin и варианты кроссплатформы&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3&gt;1.1 &lt;a href=&quot;https://t.me/apptractor&quot; target=&quot;_blank&quot;&gt;Mobile Insights by AppTractor&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Канал с дайджестами статей по мобильной разработке. Ссылки как на русскоязычные, так и на англоязычные материалы.&lt;/p&gt;
  &lt;h3&gt;1.2 &lt;a href=&quot;https://t.me/prettygeeknotes&quot; target=&quot;_blank&quot;&gt;Записки разработчицы&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Здесь и про IOS, и про Android, и про мультиплатформу от мобильной разработчицы и Google Developer Expert в одном лице.&lt;/p&gt;
  &lt;h3&gt;1.3 &lt;a href=&quot;https://t.me/mobile_developing&quot; target=&quot;_blank&quot;&gt;Мобильный разработчик&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Ранее на канале практиковались уроки по Kotlin под Android, но теперь упор на Flutter.&lt;/p&gt;
  &lt;h3&gt;1.4 &lt;a href=&quot;https://t.me/mobi_dev&quot; target=&quot;_blank&quot;&gt;Мобильная разработка&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;1.5 &lt;a href=&quot;https://t.me/mobileproglib&quot; target=&quot;_blank&quot;&gt;Библиотека мобильного разработчика&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;1.6 &lt;a href=&quot;https://t.me/ohmyflutter&quot; target=&quot;_blank&quot;&gt;Oh, my Flutter&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;2. Android&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/1c/a6/1ca68ea7-dca1-4c8f-8e6d-bcf0b799d6ee.jpeg&quot; width=&quot;1500&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;2.1 &lt;a href=&quot;https://t.me/android_broadcast&quot; target=&quot;_blank&quot;&gt;Android Broadcast&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Слишком крутой русскоязычный канал, что даже не хочется писать подводку. Как обсуждения чего-то нового, примеры кода, так и собеседования на разные уровни. Здесь невозможно не найти для себя что-то полезное и интересное.&lt;/p&gt;
  &lt;h3&gt;2.2&lt;a href=&quot;https://t.me/startandroid&quot; target=&quot;_blank&quot;&gt; StartAndroid&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Канал от создателя &lt;a href=&quot;https://startandroid.ru/ru/&quot; target=&quot;_blank&quot;&gt;одноименного сайта&lt;/a&gt;. Сам сайт для изучения основ разработки под андроид, наверняка уже с ним знакомы, кроме того, там отличные уникальные платные курсы, а канал содержит море полезных материалов и часто обновляется.&lt;/p&gt;
  &lt;h3&gt;2.3 &lt;a href=&quot;https://t.me/android_books_channel&quot; target=&quot;_blank&quot;&gt;Android books channel&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Канал с книгами. Скорее всего, как правило, обучение будет ограничиваться статьями, но на каждое правило - всегда есть свое исключение!&lt;/p&gt;
  &lt;h3&gt;2.4 &lt;a href=&quot;https://t.me/easyCodeRu&quot; target=&quot;_blank&quot;&gt;EasyCode&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Канал со стримами видео, лайвкодингом и подобной интересной кучей плюшек.&lt;/p&gt;
  &lt;h3&gt;2.5 &lt;a href=&quot;https://t.me/droidgr&quot; target=&quot;_blank&quot;&gt;Android Good Reads&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.6 &lt;a href=&quot;https://t.me/android_live&quot; target=&quot;_blank&quot;&gt;Android Live&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.7 &lt;a href=&quot;https://t.me/android_guards_today&quot; target=&quot;_blank&quot;&gt;Android Guards Today&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.8 &lt;a href=&quot;https://t.me/shitty_android&quot; target=&quot;_blank&quot;&gt;Android Дичь&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.9 &lt;a href=&quot;https://t.me/androidinfaces&quot; target=&quot;_blank&quot;&gt;Android в Лицах&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.10 &lt;a href=&quot;https://t.me/paradisecurity&quot; target=&quot;_blank&quot;&gt;paradiSEcurity&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;2.11 &lt;a href=&quot;https://t.me/mobile_native&quot; target=&quot;_blank&quot;&gt;Mobile Native&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;3. IOS&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/7b/af/7baf6e2e-3e35-4956-8a72-009d8c7e3577.png&quot; width=&quot;2468&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;3.1 &lt;a href=&quot;https://t.me/iosgr&quot; target=&quot;_blank&quot;&gt;iOS Good Reads&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;3.2 &lt;a href=&quot;https://t.me/dodoMobile&quot; target=&quot;_blank&quot;&gt;Dodo Pizza Mobile&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;3.3 &lt;a href=&quot;https://t.me/iosgt_elite&quot; target=&quot;_blank&quot;&gt;iOS Elite Talks&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;3.4 &lt;a href=&quot;https://t.me/ios_heads&quot; target=&quot;_blank&quot;&gt;iOS.Devs Camp&lt;/a&gt;&lt;/h3&gt;
  &lt;h3&gt;3.5 &lt;a href=&quot;https://t.me/ios_events&quot; target=&quot;_blank&quot;&gt;iOS.Events&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;4. Interview&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/51/a3/51a3348e-1264-415c-b641-77bb1007fef3.jpeg&quot; width=&quot;640&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;4.1 &lt;a href=&quot;https://t.me/AndroidSobes&quot; target=&quot;_blank&quot;&gt;Android Interview Review&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Давно не обновляется, но полезной информации много[0].&lt;/p&gt;
  &lt;h3&gt;4.2 &lt;a href=&quot;https://t.me/ITSobes&quot; target=&quot;_blank&quot;&gt;IT Interview Review&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Давно не обновляется, но полезной информации много[1].&lt;/p&gt;
  &lt;h3&gt;4.3 &lt;a href=&quot;https://t.me/javaquiz&quot; target=&quot;_blank&quot;&gt;Java задачи с собеседований&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Довольно активный канал, где много тестов со скриншотами кода, где предлагается выбрать верный ответ.&lt;/p&gt;

</content></entry><entry><id>noobodroid:Y4phtRZgdwy</id><link rel="alternate" type="text/html" href="https://teletype.in/@noobodroid/Y4phtRZgdwy?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=noobodroid"></link><title>Зачем нужны и как понять эти ваши архитектуры в Android?</title><published>2021-07-29T10:31:07.729Z</published><updated>2021-07-29T12:58:36.744Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/1f/cd/1fcd19fe-a188-4b72-a41a-6afeab7c3782.jpeg"></media:thumbnail><category term="android" label="Android"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/c1/3c/c13c5cb6-06d5-4583-869d-6dc4b1e24aaf.jpeg&quot;&gt;Каждый новичок, что пытается писать под Android, рано или поздно сталкивается с моментом, когда наступает понимание, что писать весь код в одной Activity или даже Fragment'е неудобно. И в этой заметке хочу рассмотреть некоторые вопросы про архитектуру. Думаю, что каждый слышал про то, какие в принципе бывают архитектурные паттерны, но на всякий случай начну с их перечисления:</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c1/3c/c13c5cb6-06d5-4583-869d-6dc4b1e24aaf.jpeg&quot; width=&quot;871&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Предисловие&lt;/h2&gt;
  &lt;p&gt;Каждый новичок, что пытается писать под Android, рано или поздно сталкивается с моментом, когда наступает понимание, что писать весь код в одной Activity или даже Fragment&amp;#x27;е неудобно. И в этой заметке хочу рассмотреть некоторые вопросы про архитектуру. Думаю, что каждый слышал про то, какие в принципе бывают архитектурные паттерны, но на всякий случай начну с их перечисления:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;MVC&lt;/li&gt;
    &lt;li&gt;MVP (VIPER и другие производные от MVP, в том числе &lt;a href=&quot;https://www.reddit.com/r/196/comments/mj7zb4/pattern_pidor/&quot; target=&quot;_blank&quot;&gt;PIDOR)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;MVVM&lt;/li&gt;
    &lt;li&gt;MVI&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Цель самой архитектуры - написание кода, который легче поддерживать. И тут отмечу важный момент. Стадии, какие прошел я и какие, как мне кажется, проходят почти все разработчики, что смотрят в сторону архитектурных решений:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;Ужас от написанного своего приложения без архитектуры.&lt;/li&gt;
    &lt;li&gt;Первые попытки написания кода на архитектурном паттерне. Этот этап характерен ощущением, что код стал более легкоподдерживаемым, но при этом самого кода становится больше. То есть, плюс к читабельности, но минус ко времени написания фичей.&lt;/li&gt;
    &lt;li&gt;Грамотное выделение абстракций и сокращение boilerplate-кода.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;С первой стадией все понятно. А вот со второй и третьей сложнее. Вторая стадия может длиться довольно долго. А третья стадия - высшая точка понимания, потому что наступает момент, когда хорошо изучены тонкости языка и код начинает быть более автоматизированным, абстрагируется все больше удобных вещей в Base-классах. &lt;/p&gt;
  &lt;p&gt;Разработчик сталкивается с разными проектами, разными нюансами и разным стеком технологий. И архитектуры, что являлась бы серебряной пулей, попросту не существует, иначе все бы разработчики писали идентичный код по сэмплу, например, от Google.&lt;/p&gt;
  &lt;p&gt;Теперь рассмотрим подробнее каждый шаблон и попробую изложить свое видение, как лучше их понять.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;MVC&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/29/ac/29ac3652-fcaf-4bec-892a-fbded49b8504.jpeg&quot; width=&quot;920&quot; /&gt;
    &lt;figcaption&gt;Model-View-Controller&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Это самый простой шаблон, где основная бизнес-логика содержится в классе Model. Мне кажется, что нет смысла долго останавливаться на данном шаблоне даже новичку и на мой взгляд погружение в архитектуру вполне нормально начинать с MVP. Но если все таки есть желание попробовать руками MVC, то рекомендую книгу &amp;quot;Android. Программирование для профессионалов&amp;quot;. В новых изданиях внимания этому шаблону уделяется вроде бы меньше, смотрел мельком, поэтому желательно рассмотреть этот вариант, если уж собрались, на основе более старых изданий, например, третьего.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;MVP&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/89/21/89213553-debf-4b9c-b80c-1efe4868eddf.jpeg&quot; width=&quot;630&quot; /&gt;
    &lt;figcaption&gt;Model-View-Presenter&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;MVP - настоящая взрослая архитектура. Мне в свое время понадобилось много времени, чтобы вообще понять, как в Android построить MVP. &lt;strong&gt;Главной ошибкой было то, что я пытался читать статьи, вникать и понимать, а не писать код. А построение архитектуры - это практический навык. &lt;/strong&gt;Есть уже написанная шикарная статья о том, как построить MVP-архитектуру: &lt;a href=&quot;https://javarush.ru/groups/posts/505-mvp-v-android-dlja-samihkh-malenjhkikh&quot; target=&quot;_blank&quot;&gt;MVP в Android для самых маленьких.&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;В чем взрослость и преимущества MVP: выраженный класс Presenter для бизнес-логики, который управляет, как View, так и Model. То есть по итогу должен получиться мегакласс, где содержится логика всего приложения и который каждому слою приказывает, что тому делать конкретно и передает необходимые для этого данные. То есть Presenter не должен содержать get-функций с возвращаемым типом. И можно прекрасно понять, что происходит на экране, читая только лишь имплиментацию Presenter&amp;#x27;а. Схематично конструктор Presenter&amp;#x27;а может выглядеть так:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot;&gt;class MainPresenter(
   val mainView: MainContract.View, 
   val mainModel: MainContract.Model
) : MainContract.Presenter { ... }&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2&gt;MVVM&lt;/h2&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/1c/f0/1cf04744-c66b-4418-80b9-fbc0c76a0c7c.png&quot; width=&quot;900&quot; /&gt;
    &lt;figcaption&gt;Для MVVM ничего не придумал :(&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Чуть более сложный для понимания шаблон, поэтому настоятельно рекомендую попробовать в первую очередь MVP. Забегу вперед и мотивирую: если освоить MVVM-шаблон, то по сути нужно будет дальше приложить минимальное усилие, чтоб познать MVI и собрать в голове полную копилку знаний об основных архитектурных паттернах проектирования Android-приложений. Первое и главное отличие в названиях слоев бизнес-логики: в MVP и его производных она хранится в Presenter, тогда как в MVVM эту роль исполняет ViewModel. Во вторых, это способ взаимодействия View-слоя и ViewModel. Это осложнено тем, что ViewModel не знает явно о View-слое, но при этом им управляет. Как такое может быть? Об этом чуть дальше.&lt;/p&gt;
  &lt;p&gt;Прежде чем начать разбираться с MVVM нужно обговорить более детально о видах взаимодействия View и ViewModel и вот какие они бывают:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Прослушивание событий&lt;/strong&gt; во ViewModel, происходящие во VIew, примеры: нажатие кнопки, изменение текста в EditText.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Изменения во ViewModel&lt;/strong&gt;, которые после configuration changes должны подтягиваться актуальные значения, примеры: пришли данные с сервера и нужно показать/скрыть виджет на View-слое, изменить текст в TextView.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Исполнение View-слоем однократных событий&lt;/strong&gt; по приказу ViewModel&amp;#x27;и, пример: показать диалог, показать тост или перейти на другой фрагмент/экран.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;Схематично ViewModel выглядит так:&lt;/p&gt;
  &lt;pre data-lang=&quot;kotlin&quot;&gt;class MainViewModel(
   val mainModel: MainContract.Model
) : ViewModel(), MainContract.ViewModel { ... }&lt;/pre&gt;
  &lt;p&gt;Понятно, что связь View с ViewModel никуда не девается, не смотря на отсутствие в конструкторе View, она лишь усложняется и варианты управления View-слоем ViewModel&amp;#x27;ю есть такие:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;связывание XML-кода и ViewModel&amp;#x27;и через DataBinding;&lt;/li&gt;
    &lt;li&gt;реализация шаблона проектирования Observer для отправки событий из ViewModel во View для изменения состояний отдельного View-widget&amp;#x27;а или даже целиком View-слоя.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;Далее немного более детально о том, как в каждом из способов разруливаются вышеназванные виды взаимодействия.&lt;/p&gt;
  &lt;h3&gt;MVVM через DataBinding&lt;/h3&gt;
  &lt;p&gt;DataBinding  - библиотека, основанная на кодогенерации и содержит в себе Observable-классы, которые лежат во ViewModel и связываются напрямую с XML-разметкой. Подробнее о работе с событиями:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Прослушивание событий &lt;/strong&gt;происходит через реализацию функций напрямую в XML-разметке, пример в виде прослушивания изменений в EditText-виджете:&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre data-lang=&quot;xml&quot;&gt;android:onTextChanged =
&amp;quot;@{(text, start, before, count) -&amp;gt; viewModel.onUsernameTextChanged(text)}&amp;quot;&lt;/pre&gt;
  &lt;p&gt;    2. &lt;strong&gt;Изменения во ViewModel &lt;/strong&gt;происходит через вышеназванные Observable-классы-обертки и подобным образом связываются с XML. Пример: мы сделали внутри viewModel поле:&lt;/p&gt;
  &lt;pre&gt; val name = new ObservableField&amp;lt;String&amp;gt;()&lt;/pre&gt;
  &lt;p&gt;Тогда связывание поля с XML будет выглядеть так:&lt;/p&gt;
  &lt;pre data-lang=&quot;xml&quot;&gt; android:text=&amp;quot;@={viewModel.name}&amp;quot;&lt;/pre&gt;
  &lt;p&gt;   3. &lt;strong&gt;Исполнение View-слоем однократных событий &lt;/strong&gt;можно реализовать через предложенный Google класс - SingleLiveEvent. Пользоваться им нужно, как обычной LiveData. Класс можно скопипастить в свой проект. Есть &lt;a href=&quot;https://proandroiddev.com/singleliveevent-to-help-you-work-with-livedata-and-events-5ac519989c70&quot; target=&quot;_blank&quot;&gt;статья, где наглядно показано, как этим всем пользоваться&lt;/a&gt;.&lt;/p&gt;
  &lt;h3&gt;MVVM через шаблон-Observer&lt;/h3&gt;
  &lt;p&gt;Для такой реализации MVVM нужно будет использовать LiveData или Kotlin Flow, что как раз и реализуют принцип шаблона Observer, а LiveData еще и согласована с жизненным циклом нашего View. Подробнее о работе с событиями:&lt;/p&gt;
  &lt;p&gt;   1. &lt;strong&gt;Прослушивание событий &lt;/strong&gt;происходит банально через колбэки. View знает     явно и хранит в себе ссылку на ViewModel, что как раз нам позволяет использовать её методы.&lt;/p&gt;
  &lt;p&gt;   2. &lt;strong&gt;Изменения во ViewModel &lt;/strong&gt;происходит через MutableLiveData или MutableStateFlow. У нас всегда на View-слое будет актуальное значение нашего конкретного виджета или всего View-слоя.&lt;/p&gt;
  &lt;p&gt;   3. &lt;strong&gt;Исполнение View-слоем однократных событий &lt;/strong&gt;можно реализовать, как в DataBinding&amp;#x27;е через SingleLiveEvent.&lt;/p&gt;
  &lt;h3&gt;Мини-резюме по MVVM&lt;/h3&gt;
  &lt;p&gt;При правильном и опытном подходе MVVM упрощает процесс написания тест-кода (в следствие меньшего количество явных связей) и по сути может являться чуть менее многословной архитектурой, чем MVP с ее производными. Из этих двух подходов рекомендую реализацию через шаблон-Observer, по двум причинам:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;В DataBinding кодогенерация, что дает ощутимое замедление времени сборки проекта.&lt;/li&gt;
    &lt;li&gt;Вчера Google выкатили релизную версию JetPack Compose, что делает подход с DataBinding&amp;#x27;ом еще менее актуальным, ведь наступает эра отказа от XML в пользу кодовой верстки экранов через Kotlin.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;Ссылки на примеры с реализацией не прикладываю. В интернете туториалов много на каждый подвид MVVM, поэтому что-то конкретное рекомендовать не буду, так как есть выбор и куча альтернатив.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2&gt;MVI&lt;/h2&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/28/f2/28f27b53-7a54-4576-9e56-1c73f748794e.jpeg&quot; width=&quot;384&quot; /&gt;
    &lt;figcaption&gt;Здесь тоже творческий кризис&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Думаю по тексту было заметно, что глобальное отличие MVP от MVVM по сути лишь во взаимодействии между View и ViewModel-Presenter&amp;#x27;ом. Так вот, мотивировал выше не зря. MVVM еще проще трансформируется в MVI, чем MVP в MVVM. Когда я только пытался изучать MVI - было мало статей и по ним не получалось понять основной принцип. И когда в очередной раз я на своем pet-проекте писал, как я думал, MVVM, то в один прекрасный момент до меня дошло, что это как раз получилась MVI, такой вот каламбур.&lt;/p&gt;
  &lt;p&gt;Идея MVI построена вокруг более пристального контроля View-слоя. У нас есть некий ViewState data-класс, который хранит в себе кучу полей, что контролируют состояние View. И из ViewModel&amp;#x27;и напрямую во View летит через Observer-шаблон только этот data-class. Кроме ViewState может быть еще Action-сущность на уровне ViewModel&amp;#x27;и. Для наглядности приведу пример: мы загружаем данные с сервера. И в зависимости от того, какие данные пришли, например, пустой список для отображения на нашем экране или нет, мы выбираем один из определенных class&amp;#x27;ов  sealed-класса Action&amp;#x27;a, вызываем функцию sendAction(Action.NotEmptyList), далее этот метод у себя под капотом вызывает onReduceState(Action.NotEmptyList). И функция onReduceState имеет возвращаемый тип ViewState, где как раз определены все наши ViewState&amp;#x27;ы через функцию копирования copy() у Data-классов.&lt;/p&gt;
  &lt;p&gt;Текстом это тяжело передать, чтоб было понятно, поэтому, как заявил в начале заметки - нужно практиковаться. И есть отличный легкий пример с реализацией подобной архитектуры без хитрющих абстракций, который вполне можно понять, поэтому оставляю ссылки. Проект многомодульный, и дабы новички не терялись, оставлю ссылки так: &lt;a href=&quot;https://github.com/igorwojda/android-showcase/tree/main/feature_album/src/main/kotlin/com/igorwojda/showcase/feature/album/presentation/albumlist&quot; target=&quot;_blank&quot;&gt;пример одного экрана&lt;/a&gt;, наглядная абстракция &lt;a href=&quot;https://github.com/igorwojda/android-showcase/blob/3f30d3333f06288adc6f3a1b31198fbd50b1c3aa/app/src/main/kotlin/com/igorwojda/showcase/base/presentation/viewmodel/BaseViewModel.kt&quot; target=&quot;_blank&quot;&gt;BaseViewModel.&lt;/a&gt;&lt;/p&gt;

</content></entry></feed>