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

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

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

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

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

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

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

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

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

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

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

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@noobodroid/Ys10aJyt55d</guid><link>https://teletype.in/@noobodroid/Ys10aJyt55d?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid</link><comments>https://teletype.in/@noobodroid/Ys10aJyt55d?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid#comments</comments><dc:creator>noobodroid</dc:creator><title>NooboDroid-навигация</title><pubDate>Sun, 01 Aug 2021 23:59:26 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/9d/8b/9d8b27eb-8258-4734-b1a6-0382b81a618c.png"></media:content><description><![CDATA[Оглавление блога. Все заметки разбиты на категории с кликабельными ссылками.]]></description><content:encoded><![CDATA[
  <p id="vIVO">Оглавление блога. Все заметки разбиты на категории с кликабельными ссылками.</p>
  <p data-align="right" id="aH8m"><em>Дата запуска блога: 22 июля 2021</em></p>
  <p data-align="center" id="ywqw"></p>
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 data-align="center" id="2AUg">Android</h2>
    <h3 id="MKvV">1. <a href="https://teletype.in/@noobodroid/Y4phtRZgdwy" target="_blank">Зачем нужны и как понять эти ваши архитектуры в Android?</a></h3>
    <h3 id="XDZL">2. <a href="https://teletype.in/@noobodroid/joA7LpCuhQ-" target="_blank">Как развивалась работа с кнопкой в Android?</a></h3>
    <h3 id="VEfu">3. <a href="https://teletype.in/@noobodroid/hgt--QlAUXL" target="_blank">Android-NoobLabs: RxJava2 и Kotlin Coroutines</a></h3>
  </section>
  <p id="bGU7"></p>
  <section style="background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 data-align="center" id="PJhz">Общее</h2>
    <h3 id="47AN">1. <a href="https://teletype.in/@noobodroid/HZ0OCYtAUZv" target="_blank">ООП. От создания до сегодняшних дней</a></h3>
    <h3 id="piYY">2. <a href="https://teletype.in/@noobodroid/hT5MmoXjJvn" target="_blank">Полиморфизм и его виды</a></h3>
    <h3 id="Lb6m">3. <a href="https://teletype.in/@noobodroid/7N_Q6lhaolx" target="_blank">Немного про сложность алгоритмов</a></h3>
    <h3 id="orxF">4. <a href="https://teletype.in/@noobodroid/QGepGDWvM-T" target="_blank">Зачем мне эти ваши структуры данных?</a></h3>
    <h3 id="Oidj">5. <a href="https://teletype.in/@noobodroid/7AoQoWax7QC" target="_blank">BCS (Base Computer Science): Оглавление</a></h3>
  </section>
  <p id="hkw5"></p>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 data-align="center" id="WlXF">Поиск работы и резюме</h2>
    <h3 id="9YX9">1. <a href="https://teletype.in/@noobodroid/TrV8_eiiHr7" target="_blank">Тернистый путь до Android-разработчика</a> (моя история трудоустройства)</h3>
    <h3 id="Pvmf">2. <a href="https://teletype.in/@noobodroid/ggvxWdNuI61" target="_blank">Вопросы junior-IT-шника работодателю</a></h3>
    <h3 id="KUPj">3. <a href="https://teletype.in/@noobodroid/N_UTN-u5hxW" target="_blank">Как IT-новичку победить процесс найма. Резюме</a></h3>
  </section>
  <p id="omQo"></p>
  <section style="background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 data-align="center" id="nwVt">Полезные подборки</h2>
    <h3 id="VtGV">1. <a href="https://teletype.in/@noobodroid/xDKUOUjZOVD" target="_blank">Что читать в Telegram по мобильной разработке?</a></h3>
    <h3 id="OOCI">2. <a href="https://teletype.in/@noobodroid/ooX6Ui0L9sK" target="_blank">Мобильная разработка: YouTube-каналы и подкасты на русском языке</a></h3>
  </section>

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

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@noobodroid/AjF3wPU_7k2</guid><link>https://teletype.in/@noobodroid/AjF3wPU_7k2?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid</link><comments>https://teletype.in/@noobodroid/AjF3wPU_7k2?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid#comments</comments><dc:creator>noobodroid</dc:creator><title>BCS: Потоки и процессы</title><pubDate>Sun, 01 Aug 2021 10:03:53 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/a3/d7/a3d7ff03-b749-4164-8af3-e7715eb9b849.jpeg"></media:content><category>Computer Science</category><description><![CDATA[<img src="https://img3.teletype.in/files/ab/65/ab65dfea-e379-45a0-8ec0-00609f1224cf.jpeg"></img>Процесс - совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированны друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие может осуществляться только с помощью специальных средств). Для каждого процесса ОС создает &quot;виртуальное адресное пространство&quot;, к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система отвечает за то, как виртуальное пространство процессов проецируется на физическую память. Резюмируя, процесс - понятие на уровне операционной системы.]]></description><content:encoded><![CDATA[
  <figure class="m_original">
    <img src="https://img3.teletype.in/files/ab/65/ab65dfea-e379-45a0-8ec0-00609f1224cf.jpeg" width="640" />
  </figure>
  <p><strong>Процесс</strong> - совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированны друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие может осуществляться только с помощью специальных средств). Для каждого процесса ОС создает &quot;виртуальное адресное пространство&quot;, к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система отвечает за то, как виртуальное пространство процессов проецируется на физическую память. Резюмируя, процесс - понятие на уровне операционной системы.</p>
  <p><strong>Поток</strong> - использует выделенные для процесса ресурсы и является способом выполнения процесса. Главный поток выполняет main-функцию и завершается. При выполнении главного потока могут порождаться дополнительные потоки. Потоки одного процесса могут обмениваться данными между собой.</p>
  <p><strong>Поток-демон</strong> - поток работающий в фоновом режиме. Если все потоки не демоны закончили свою работу, то программа завершается, не смотря на работу потоков-демонов.</p>
  <p><strong>Монитор</strong> - дополнительная надстройка над mutex&#x27;ом, в Java реализуется с помощью  ключевого слова synchronized.</p>
  <p><strong>Семафор</strong> - средство для синхронизации доступа к какому-либо ресурсу. Особенность в том, что при создании механизма синхронизации он использует считчик, который указывает сколько потоков одновременно могут получать доступ к общему ресурсу. Семафоры в Java представлены специальным классом Semaphore.</p>
  <p><strong>Mutex</strong> - специальный объект для синхронизации потоков, прикреплен к каждому объекту Java, поэтому есть у всех экземпляров класса. Mutex - одноместный семафор.</p>
  <h2><strong>*ЗАМЕТКА НА СТАДИИ РАЗРАБОТКИ*</strong></h2>

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

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@noobodroid/7AoQoWax7QC</guid><link>https://teletype.in/@noobodroid/7AoQoWax7QC?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid</link><comments>https://teletype.in/@noobodroid/7AoQoWax7QC?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid#comments</comments><dc:creator>noobodroid</dc:creator><title>BCS: Оглавление</title><pubDate>Sun, 01 Aug 2021 09:52:12 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/23/c6/23c664ad-437a-4871-8b6a-318ac5454047.jpeg"></media:content><category>Computer Science</category><description><![CDATA[<img src="https://img3.teletype.in/files/6b/93/6b93ab64-7495-4afd-ae65-7cf96110492e.jpeg"></img>BCS - Base Computer Science. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.]]></description><content:encoded><![CDATA[
  <figure class="m_column">
    <img src="https://img3.teletype.in/files/6b/93/6b93ab64-7495-4afd-ae65-7cf96110492e.jpeg" width="1500" />
  </figure>
  <section style="background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p><strong>BCS - Base Computer Science</strong>. В рамках данной рубрики заметок буду кратко рассматривать какие-то определения, что часто могут встретиться на собеседованиях или в работе. При этом сюда будут входить вопросы скорее не по Android, а по всему тому, что его окружает, то есть некие общие вопросы на пересечении разных сфер.</p>
  </section>
  <h2>1. <a href="https://teletype.in/@noobodroid/AjF3wPU_7k2" target="_blank">Процессы и потоки</a></h2>
  <h2>2. <a href="https://teletype.in/@noobodroid/-iLe27Y5qLz" target="_blank">Сеть</a></h2>
  <h2>*ЗАМЕТКА НА СТАДИИ РАЗРАБОТКИ*</h2>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@noobodroid/joA7LpCuhQ-</guid><link>https://teletype.in/@noobodroid/joA7LpCuhQ-?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid</link><comments>https://teletype.in/@noobodroid/joA7LpCuhQ-?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=noobodroid#comments</comments><dc:creator>noobodroid</dc:creator><title>Как развивалась работа с кнопкой в Android?</title><pubDate>Fri, 30 Jul 2021 17:35:27 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/af/ef/afefbbf8-eb59-4326-bd94-2abc3e5270b9.jpeg"></media:content><category>Android</category><description><![CDATA[<img src="https://img3.teletype.in/files/a9/e6/a9e6a4fe-5e04-4db0-9bdb-36c2227c0b99.jpeg"></img>На днях вышел Jetpack Compose, поэтому решил ностальгически пройтись по тем способам работы с View-слоем, какие были популярны у Android-разработчиков ранее, потому что работа с XML на View-слое уходит в прошлое.]]></description><content:encoded><![CDATA[
  <section style="background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <figure class="m_original">
      <img src="https://img3.teletype.in/files/a9/e6/a9e6a4fe-5e04-4db0-9bdb-36c2227c0b99.jpeg" width="418" />
      <figcaption>Кнопки мои кнопки</figcaption>
    </figure>
  </section>
  <p>На днях вышел Jetpack Compose, поэтому решил ностальгически пройтись по тем способам работы с View-слоем, какие были популярны у Android-разработчиков ранее, потому что работа с XML на View-слое уходит в прошлое.</p>
  <h2>0. Способы &quot;из коробки&quot;</h2>
  <h3>0.1 findViewById</h3>
  <p>findViewById - нативный вариант работы с кнопкой. Итак, у нас есть в XML какая-то кнопка. Чтобы работать с ней из Java или Kotlin кода - нужно в XML задать ей ID:</p>
  <pre data-lang="xml"> ...
 &lt;Button
    android:id=&quot;@+id/button&quot;
    android:text=&quot;Button&quot;
    ... /&gt;
...</pre>
  <p>При компиляции приложения aapt создаст класс R, который содержит ресурс IDs для всех ресурсов в каталоге res.</p>
  <p>Как правило, с кнопкой нужно работать не в одном каком-то методе жизненного цикла, но и обращаться к ней из класса бизнес-логики, то есть Presenter&#x27;а или ViewModel&#x27;и и нужно, чтобы кнопка была объявлена полем, заодно повесим слушать кликов что примерно будет выглядеть так:</p>
  <pre data-lang="java">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, 
      &quot;Здесь обработка клика&quot;, 
      Toast.LENGTH_SHORT).show();
   }
}</pre>
  <h3>0.2 onClick в XML</h3>
  <p>Этот добавился несколько позже и позволяет задать вызов метода из XML-разметки напрямую. И данный способ не работает во фрагментах, только в Activity. Выглядит это так:</p>
  <pre data-lang="xml"> ...
 &lt;Button
    android:id=&quot;@+id/button&quot;
    android:text=&quot;Button&quot;
    android:onClick=&quot;onClickButtons&quot;
    ... /&gt;
 ...</pre>
  <pre data-lang="java">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, 
      &quot;Здесь обработка клика&quot;, 
      Toast.LENGTH_SHORT).show();
   }
}</pre>
  <h3>0.3 OnClickListener</h3>
  <p>Здесь нужно было просто реализовать интерфейс в Activity или Fragment&#x27;е, что на в итоге приводит к такому:</p>
  <pre data-lang="java">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, 
      &quot;Здесь обработка клика&quot;, 
      Toast.LENGTH_SHORT).show();
   }
}</pre>
  <p></p>
  <hr />
  <h2>2. ButterKnife</h2>
  <p>Разработчики - люди ленивые. И им изначально казалось, что совершается слишком много телодвижений для начала работы со виджетом. И большую популярность обрела библиотека <a href="https://github.com/JakeWharton/butterknife" target="_blank">ButterKnife</a>, которую написал <a href="https://itsobes.ru/AndroidSobes/kto-takoj-dzhejk-vorton/" target="_blank">Jake Wharton.</a> Первая версия библиотеки вышла 5 марта 2013 года. Как выглядел тот же самый, но чуть расширенный код относительно того, что выше (пример позволяет обрабатывать клик двух кнопок):</p>
  <pre data-lang="java">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,
         &quot;Здесь обработка клика button&quot;,
         Toast.LENGTH_SHORT).show();
         break;
         
         case R.id.button2:
         Toast.makeText(
         this, 
         &quot;Здесь обработка клика button2&quot;,
         Toast.LENGTH_SHORT).show();
         break;
      }
   }
}</pre>
  <h2></h2>
  <hr />
  <h2>3. DataBinding</h2>
  <p>В 2015 году уже были release-candidate версии этого решения от Google. Точную дату выхода релизной версии не помню, но по-моему активно заговорили о таком решении после Google IO 2017. Нельзя сказать, что оно было очень популярным, так как суть работы происходит через кодогенерацию, что увеличивает время сборки проектов. Это плохо тем, что в сегодняшние дни очень крупные компании стараются модуляризировать свою архитектуру, чтобы при каких-либо изменениях пересобиралась как можно меньшая часть проекта и соответственно уменьшалось время сборки, хотя они даже не используют DataBinding. Сама суть DataBindinga в связывании напрямую xml-кода и ViewModel-класса бизнес-логики, что позволяло даже писать Java-код в XML, то есть у нас напрямую вызывалась функция класса ViewModel&#x27;и через лямбда-выражение:</p>
  <pre data-lang="xml">...
&lt;layout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;&gt;
    &lt;data&gt;
    &lt;variable
    name=&quot;viewModel&quot;
    type=&quot;com.example.project.MainViewModel&quot; /&gt;
    ...
 &lt;Button
    android:id=&quot;@+id/button&quot;
    android:text=&quot;Button&quot;
    android:onClick=&quot;@{() -&gt; viewModel.onClickButtons()}&quot;
    ... /&gt;
...</pre>
  <h2></h2>
  <hr />
  <h2>4. Kotlin Synthetyc</h2>
  <p>Если верить тому, как мельком я посмотрел доступные GitHub-репозитории, то разработка Kotlin Synthetyc началась примерно примерно в середине 2016 года. Но данный способ работы со View хоть и был немногословным, но быстро стал Deprecated в версии Kotlin 1.4.20, что датирована 5 мая 2021 года. Принцип работы основан на генерации кода плагином, который автоматически подтягивал нужный import.</p>
  <pre data-lang="kotlin"> 
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, 
      &quot;Здесь обработка клика&quot;, 
      Toast.LENGTH_SHORT).show();
   }
}</pre>
  <p></p>
  <hr />
  <h2>5. ViewBinding</h2>
  <p>В феврале 2020 года с выходом Android Gradle plugin 3.6.0 - разработчики смогли подключать ViewBinding для работы со View в своих проектах. Данный метод тоже основан на генерации binding-классов, но ликвидирован недостаток DataBindinga в виде очень долгого времени сборки, ну и соответственно нет возможности писать код в XML.</p>
  <pre data-lang="kotlin">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, 
      &quot;Здесь обработка клика&quot;, 
      Toast.LENGTH_SHORT).show();
   }
}</pre>
  <p></p>
  <hr />
  <section style="background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2>6. Jetpack compose </h2>
    <p>28 июля 2021 года - по-настоящему революционная дата для Android-разработчиков. В этот день сменился полностью подход работы со View-слоем приложения. Если во всех вышеназванных способах суть заключалась в различных попытках связать XML-код и Java/Kotlin код, то вышедший в релизной версии Jetpack Compose предлагает декларативную верстку UI прямо в Kotlin-классах. И этот тот подход, какой определенно вытеснит в будущем XML.</p>
    <pre data-lang="kotlin">
class MainActivity : ComponentActivity() {

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

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


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

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

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

]]></content:encoded></item></channel></rss>