<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Aniket Kadam</title>
    <description>The latest articles on Forem by Aniket Kadam (@aniketsmk).</description>
    <link>https://forem.com/aniketsmk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F37073%2F0b757ac1-6dbb-4c02-acd2-41469a9dac14.jpg</url>
      <title>Forem: Aniket Kadam</title>
      <link>https://forem.com/aniketsmk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aniketsmk"/>
    <language>en</language>
    <item>
      <title>Write-Only Social Media</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Sun, 16 May 2021 04:05:44 +0000</pubDate>
      <link>https://forem.com/aniketsmk/write-only-social-media-31d0</link>
      <guid>https://forem.com/aniketsmk/write-only-social-media-31d0</guid>
      <description>&lt;p&gt;Social media can help you look for jobs, be visible to people and get word out about things that could help others. At what cost though?&lt;/p&gt;

&lt;p&gt;The current disaster is an unevenly distributed pandemic but &lt;br&gt;
there have always been unevenly distributed disasters as one side of the world recovers and the other reels.&lt;/p&gt;

&lt;p&gt;If you're in the part that's currently reeling it can be hard to open up twitter to share resources or job hunt without a forceful reminder of what the state of everything is.&lt;/p&gt;

&lt;p&gt;To solve this problem I've been using tools that are normally used by brands to maintain a social presence, a social media tool like &lt;a href="https://buffer.com/"&gt;Buffer&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Write Only Social Media
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://buffer.com/"&gt;Buffer&lt;/a&gt; is particularly helpful because it has free accounts, is easy to use to get set up for LinkedIn and Twitter and keeps the peace-wrecking "feed" off your eyeballs.&lt;/p&gt;

&lt;p&gt;With it you could write and post things without ever having to look at what else is happening.&lt;/p&gt;

&lt;p&gt;If you turn on emails for twitter DM's, you won't miss those either and going straight to &lt;a href="http://twitter.com/messages/"&gt;http://twitter.com/messages/&lt;/a&gt; will bypass the feed again to reply to them.&lt;/p&gt;




&lt;p&gt;Stay safe, stay home if you're in the currently unlucky country/city and hopefully this too will pass.&lt;/p&gt;

</description>
      <category>social</category>
      <category>media</category>
      <category>anxiety</category>
    </item>
    <item>
      <title>How to Raise Hell with a Vaccine Booking System</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Mon, 10 May 2021 05:20:03 +0000</pubDate>
      <link>https://forem.com/aniketsmk/how-to-raise-hell-with-a-vaccine-booking-system-fob</link>
      <guid>https://forem.com/aniketsmk/how-to-raise-hell-with-a-vaccine-booking-system-fob</guid>
      <description>&lt;p&gt;If you don't know about &lt;a href="http://cowin.gov.in/" rel="noopener noreferrer"&gt;Cowin&lt;/a&gt; consider yourself lucky. It's the national vaccine slot booking website created by India.&lt;br&gt;
The population of Mumbai was 12.5 million at last count. It currently vaccinates approximately 58,000 people per day, down from a high of approximately 64,000 a few weeks ago. At this rate it'd take over half a year to vaccinate everyone with a single shot. More than a year to cover both shots.&lt;/p&gt;

&lt;p&gt;Here's how Cowin works.&lt;/p&gt;

&lt;p&gt;You can only login with an OTP send to your mobile number. This registration lasts for 15 minutes until you are logged out.&lt;br&gt;
You then register upto 4 people on 1 mobile number and choose to schedule them to get vaccinated. You are presented with a list of vaccination centers.&lt;/p&gt;

&lt;p&gt;Here's the thing though, the page on which you desperately search for open slots, doesn't check if you're authenticated. You can easily go past the 15 minute timer and be logged out but it won't tell you until you actually go to schedule a shot from a rare open slot. The time it wastes to get another OTP guarantees you'll never see that slot again.&lt;/p&gt;

&lt;p&gt;Many people were concerned that people in tech were using bots to book slots, which they were. Now here's how to raise hell. Your system has a problem with bots.&lt;/p&gt;

&lt;p&gt;Because your government &lt;a href="https://scroll.in/article/994319/indias-vaccine-policy-mess-is-due-to-its-reliance-on-technocrats-instead-of-public-health-experts" rel="noopener noreferrer"&gt;only gave near-monopoly profits to two companies manufacturing vaccines&lt;/a&gt; and then delayed &lt;a href="https://scroll.in/latest/993929/there-were-no-orders-covid-vaccine-supply-shortage-to-go-on-till-july-says-adar-poonawalla" rel="noopener noreferrer"&gt;ordering new vaccines by a month&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are a whole bunch of usability absolute nightmares that are wasting the time of every Indian playing this cursed game every night while desperately trying to save their lives in the pandemic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Double Scrolling to See the List of Slots
&lt;/h1&gt;

&lt;p&gt;There is also a double scrolling bar. One which scrolls the entire page of useless graphics and another much smaller window within which the vaccination slots scroll.&lt;br&gt;
Which means the size of the window dedicated to showing the slots is not much taller than the size dedicated to showing a picture of our prime minister.&lt;/p&gt;

&lt;p&gt;Do I as a user care about the graphics on the page limiting how many vaccination centres I can see? Absolutely not. This means I have to first move my mouse within the smaller scrolling section and then scroll. Adding anxiety.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdc6wvhbol5993srlq2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdc6wvhbol5993srlq2i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The 18-45 Filter
&lt;/h1&gt;

&lt;p&gt;You need to filter by 18+ or there are too many centres. Each time you click 'Search' to look for vaccines you need to select 18+ again because the selection is cleared.&lt;br&gt;
Which means along with clicking on the search button every few seconds, you &lt;strong&gt;again&lt;/strong&gt; have to click on the 18+ button.&lt;/p&gt;

&lt;p&gt;Do I as a user want my choice reset and strain my hands constantly? Why in the hell would I?&lt;/p&gt;

&lt;p&gt;Fun fact: The API call still retrieves information for all slots. The filtering is done client side.&lt;/p&gt;

&lt;h1&gt;
  
  
  Time Slots
&lt;/h1&gt;

&lt;p&gt;If you do see a rare centre with open slots, each centre has 4 time slots available. You need to play an elaborate guessing game to guess which slot might be free.&lt;/p&gt;

&lt;p&gt;Do I as a consumer care right now whether my slot is in the morning or evening? I don't give a damn. Eliminate the illusion of choice by removing this option entirely and just allocate whatever. It will save server time and user anxiety.&lt;/p&gt;

&lt;p&gt;Give us ONE option for the centre and none for the time. I promise you almost no one cares what time in the day they can save their lives.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Errors
&lt;/h1&gt;

&lt;p&gt;While the government tries very hard to pretend like the site never crashes, basically every single person who has made it down to the time slots and clicked confirm has encountered Error code 500, which means there's a bug on the server side. An exception related to bad coding that means 75% of people who are quick enough to get to slots and attempt to book, get thrown out because of the error anyway.&lt;/p&gt;

&lt;p&gt;The technical person in charge has decided this should be a silent error and just not tell people anything. The only thing that happens is that the confirm button becomes available to be pressed again.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;They added captchas to chowkidar (guard) the site. But the most important thing in product development is "What are your users trying to do?"&lt;br&gt;
Do they want the luxury of picking a time slot? Selecting over and over that they're above 18 every few seconds? Do they want to keep a watch on the time to make sure it hasn't been 15 minutes because they're auto-logged out? Do they want to play this cursed game every night?&lt;/p&gt;

&lt;p&gt;A user-hostile, very Indian way of solving this problem is "strict-action", "captchas" punishment and attacks.&lt;/p&gt;

&lt;p&gt;It overloads the servers at a specific time everyday and sends the country into panic attacks over times and notifications and reds and greens.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solutions
&lt;/h1&gt;

&lt;p&gt;Something where every person registered is put into a queue, with a mild preferences as to where and when which can be analysed at leisure and people sent SMS' about when their slot might be, and the day that it is will avoid this national disgrace.&lt;/p&gt;

&lt;p&gt;To do this however, we have to abandon something truly Indian. The concept of "strict action" and move towards smarter solutions that work for the people who need them.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Kotlin Flow - Implementing an Android Timer</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Tue, 13 Apr 2021 17:52:25 +0000</pubDate>
      <link>https://forem.com/aniketsmk/kotlin-flow-implementing-an-android-timer-ieo</link>
      <guid>https://forem.com/aniketsmk/kotlin-flow-implementing-an-android-timer-ieo</guid>
      <description>&lt;p&gt;How complex could a timer be? We're about to find out in this dive into understanding Kotlin Flows by implementing one.&lt;/p&gt;

&lt;p&gt;We'll be building out the logic with Kotlin Flows in a ViewModel and showing the timer with a Jetpack Compose, Composable. State will be represented with &lt;a href="https://developer.android.com/kotlin/flow/stateflow-and-sharedflow" rel="noopener noreferrer"&gt;StateFlow&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's in a timer?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;You have an initial state, when the timer's inactive.&lt;/li&gt;
&lt;li&gt;You have it counting down after it's tapped.&lt;/li&gt;
&lt;li&gt;It resets when it's done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a jump start by looking at the code &lt;a href="https://github.com/AniketSK/ComposeFlowTimer" rel="noopener noreferrer"&gt;here it is&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The UI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faecw4xc8kutpb720n7lh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faecw4xc8kutpb720n7lh.gif" alt="A purple ring, with a black background. It starts with a - inside the ring. Once it's tapped, the - turns into the number 60 and begins counting down. It's tapped again and turns into a - again."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI part of the timer will be represented by a CircularProgressIndicator and a Text that shows the value of the countdown numerically. The timer only starts when it's tapped and another tap resets it.&lt;/p&gt;

&lt;p&gt;Here's the UI code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;TimerDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timerState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toggleStartStop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CircularProgressIndicator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;timerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;progressPercentage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clickable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;toggleStartStop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;displaySeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;TimerState is a helper class. All it contains is the progress percentage (When 30 seconds elapses on a 60 second timer, that's 0.5% progress for the CircularProgressIndicator), and the text to show for seconds remaining.&lt;/p&gt;

&lt;p&gt;With TimerState, you can provide the remaining seconds and total seconds and it calculates the rest of the information for the Composable.&lt;/p&gt;

&lt;p&gt;Here's the code for TimerState &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;secondsRemaining&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;textWhenStopped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;displaySeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondsRemaining&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="n"&gt;textWhenStopped&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Show 100% if seconds remaining is null&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;progressPercentage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondsRemaining&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFloat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Always implement toString from Effective Java Item 9&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Seconds Remaining $secondsRemaining, totalSeconds: $totalSeconds, progress: $progressPercentage"&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are some nuances about it you can read or skip. The nuances are, what do you show when the timer is stopped? For this data class, stopped is represented by the int for remaining seconds being null. By providing only &lt;em&gt;secondsRemaining&lt;/em&gt; and &lt;em&gt;totalSeconds&lt;/em&gt; the rest of the information which our TimerDisplay needs is calculated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow of Logic
&lt;/h2&gt;

&lt;p&gt;I'm going to encapsulate the logic for the timer in a class called a &lt;em&gt;TimerUseCase&lt;/em&gt;.&lt;br&gt;
Here's how it's going to work.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;asFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Effectively creates a list of numbers from the total number of seconds to 0 and emits them one by one as a Flow.&lt;br&gt;
If totalSeconds was 5, we'd get 5,4,3,2,1,0 emitted.&lt;br&gt;
In the final code we'd subtract this by 1 but we'll see why in a bit. Psst, it's related on the onStart.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;asFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Means whenever an item is emitted from this Flow, first we'll wait for 1 second and then let it proceed down the chain.&lt;br&gt;
This is how the ticking of the timer is implemented.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimeState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This could've just been the next in the chain however there's a problem if we write it that way.&lt;br&gt;
Here the only thing we're doing is creating a TimeState but if there was a more complex operation to be performed, it could take several milliseconds and now we're forcing time drift in the flow chain.&lt;br&gt;
Here's an example. If it takes 1 second to emit the next remaining second but another 200ms to create an object like TimeState, then 1200ms have passed before the next item can be emitted. If this cycle repeats many times over the timer wouldn't be accurate anymore.&lt;/p&gt;

&lt;p&gt;So we need something in between. Here's the actual code with 'conflate' being used to run the transform function concurrently (at the same time) on a separate thread from the one that ticks for time.&lt;/p&gt;

&lt;p&gt;Also if the code was left as it was, you'd only see the timer begin to tick one second after you tapped it. We want it immediately showing the full time and then begin to tick so we make two modifications.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the Flow is engaged, we immediately emit the total seconds as the first value on the countdown. Which means emitting totalSeconds with onStart.
```kotlin
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;.onStart { emit(totalSeconds) }&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Then, the flow actually emits its first delayed value. The one for the next second. That's why the flow starts with
```kotlin


(totalSeconds - 1 downTo 0).asFlow()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here's the code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

    &lt;span class="cm"&gt;/**
     * The timer emits the total seconds immediately.
     * Each second after that, it will emit the next value.
     */&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;initTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimeState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;asFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Emit total - 1 because the first was emitted onStart&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Each second later emit a number&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onStart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Emit total seconds immediately&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conflate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// In case the creating of State takes some time, conflate keeps the time ticking separately&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimeState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Additional conditions
&lt;/h2&gt;

&lt;p&gt;We're not done yet!&lt;br&gt;
As it is, the timer can't handle being cancelled nor resetting to a default value once it's done counting. For that we'll need to set &lt;em&gt;onCompletion&lt;/em&gt; when it's launched.&lt;/p&gt;

&lt;p&gt;Here it is:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;_timerStateFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MutableStateFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StateFlow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We'll need to create a private MutableStateFlow to emit the TimerState and a public StateFlow to be bound to the composeable.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toggleTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timerScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the toggleTime function is called, if there was no Coroutine Job running earlier, it begins a new one.&lt;br&gt;
If this is tapped again, it will cancel the currently running job.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timerScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;initTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCompletion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;onCompletion&lt;/em&gt; block is like a 'finally'. Whether the Flow completed normally or with an error, the onCompletion block will be called and reset the TimeState so the UI can be reset.&lt;br&gt;
Also in the collect, we put the received TimeState into the TimerStateFlow for the UI to observe.&lt;/p&gt;

&lt;p&gt;Here's it all together.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerUseCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerScope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CoroutineScope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;_timerStateFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MutableStateFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StateFlow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toggleTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timerScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;initTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCompletion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cm"&gt;/**
 * The timer emits the total seconds immediately.
 * Each second after that, it will emit the next value.
 */&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;initTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="c1"&gt;//        generateSequence(totalSeconds - 1 ) { it - 1 }.asFlow()&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;asFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Emit total - 1 because the first was emitted onStart&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Each second later emit a number&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onStart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Emit total seconds immediately&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conflate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// In case the operation onTick takes some time, conflate keeps the time ticking separately&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  The ViewModel
&lt;/h1&gt;

&lt;p&gt;Doing all that work in the UseCase frees up the ViewModel to be very clean like so.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerVm&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerIntent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TimerUseCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewModelScope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StateFlow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimerState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timerStateFlow&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toggleStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And finally it's used in the MainActivity like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;vm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TimerVm&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;timerState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timerStateFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collectAsState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;TimerDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;toggleStart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You've now got a great timer that'll always behave! You might have learned a few things about encapsulation, coroutines and Jetpack Compose along the way too!&lt;/p&gt;




&lt;p&gt;I'm on the lookout for a Senior Android position with great customer impact, a great team and great compensation. Let me know if you're hiring! Also open to consulting contracts.&lt;/p&gt;

</description>
      <category>jetpackcompose</category>
      <category>kotlin</category>
      <category>flow</category>
      <category>android</category>
    </item>
    <item>
      <title>Snackbars Without Scaffolds (and why you should avoid them)</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Sun, 11 Apr 2021 14:36:45 +0000</pubDate>
      <link>https://forem.com/aniketsmk/snackbars-without-scaffolds-and-why-you-should-avoid-them-4nac</link>
      <guid>https://forem.com/aniketsmk/snackbars-without-scaffolds-and-why-you-should-avoid-them-4nac</guid>
      <description>&lt;h1&gt;
  
  
  Considerations
&lt;/h1&gt;

&lt;p&gt;Sometimes you might run into a situation where you need a Snackbar in a layout that can't have a Scaffold.&lt;br&gt;
For instance, if you wanted a &lt;em&gt;modal&lt;/em&gt; BottomSheet &lt;em&gt;and&lt;/em&gt; a Scaffold, those aren't two things you can easily use together. Mainly because the ModalBottomSheetLayout doesn't have a SnackbarHost and doesn't play nicely with other wrapping layouts.&lt;br&gt;
In this case, you'd have to create and more importantly &lt;em&gt;place&lt;/em&gt; your own SnackBarHost.&lt;/p&gt;

&lt;h1&gt;
  
  
  Placement Methods
&lt;/h1&gt;

&lt;p&gt;Take a look at the Scaffold.kt's &lt;a href="https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/src/commonMain/kotlin/androidx/compose/material/Scaffold.kt;l=272" rel="noopener noreferrer"&gt;code for placing Snackbars&lt;/a&gt;, it involves measuring the Snackbar and calculating an avoidance of the Fab button and such.&lt;br&gt;
Perhaps you'd reconsider your layout to see if it's worth this?&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating it
&lt;/h1&gt;

&lt;p&gt;It's quite simple to create it though!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SnacksNoScafs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;snackState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;SnackbarHostState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;snackScope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberCoroutineScope&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nc"&gt;SnackbarHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hostState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snackState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;launchSnackBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;snackScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;snackState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showSnackbar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sup? Here's some snacks."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;launchSnackBar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Show Snackbar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Without additional placement information the host ends up at the top like so:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbajiis42cp8vocqb5s75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbajiis42cp8vocqb5s75.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you end up needing to use these two and how you dealt with the tradeoffs yourself.&lt;/p&gt;

&lt;p&gt;This was valid as of Jetpack Compose beta 3.&lt;/p&gt;




&lt;p&gt;I'm on the lookout for a Senior Android position with great customer impact, a great team and great compensation. Let me know if you're hiring! Also open to consulting contracts.&lt;/p&gt;

</description>
      <category>android</category>
      <category>jetpackcompose</category>
      <category>snackbar</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>How to Add a Snackbar to Jetpack Compose</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Wed, 07 Apr 2021 06:32:22 +0000</pubDate>
      <link>https://forem.com/aniketsmk/how-to-add-a-snackbar-to-jetpack-compose-1ehj</link>
      <guid>https://forem.com/aniketsmk/how-to-add-a-snackbar-to-jetpack-compose-1ehj</guid>
      <description>&lt;p&gt;Snackbars are now the default way to show transitory information in Android. They replaced Toasts a while ago and for good reason!&lt;/p&gt;

&lt;p&gt;If you're using Jetpack Compose, it's a bit of a procedure to use them though. Here's how you do it.&lt;/p&gt;

&lt;p&gt;If you need a quick refresher, here's the answer. Don't worry if it doesn't make sense, I'll explain all the components by the end of the article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;snackbarCoroutineScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;scaffoldState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snackbarHostState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showSnackbar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Snacks in Compose"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: This is valid as of Jetpack Compose Beta 3 (1.0.0-beta03)&lt;/p&gt;

&lt;h1&gt;
  
  
  Starting With a Button
&lt;/h1&gt;

&lt;p&gt;We'll start off with a Compose UI that has a button which prints a log and then instead of a log, we'll get to a point where it can show a Snackbar.&lt;/p&gt;

&lt;p&gt;Here's that button printing a log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;MainScreenUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Button Clicked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click Me"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a conventional Snackbar, you need a Scaffold. A scaffold is a container that makes it easy to add all kinds of standard UI like top bars, bottom bars and even places the Snackbar conveniently for you. The 'state' of the Snackbar is held within the state of the Scaffold.&lt;/p&gt;

&lt;p&gt;I'm guessing you already have some UI in a Compose function so just add a Scaffold to the top.&lt;/p&gt;

&lt;h1&gt;
  
  
  Halfway There, Adding the Scaffold
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;MainScreenUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;Scaffold&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Button Clicked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click Me"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;a href="https://developer.android.com/reference/kotlin/androidx/compose/material/ScaffoldState"&gt;ScaffoldState&lt;/a&gt; so we can get at the SnackbarState within it.&lt;/li&gt;
&lt;li&gt;Snackbars are generally animated and do some background work to appear so we also need a CoroutineScope to run their background work in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Personally I think it's a bit strange that we've got to handle the background animation of the Snackbar ourselves but that's the api.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting To the SnackbarState
&lt;/h1&gt;

&lt;p&gt;First we'll add the ScaffoldState&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;MainScreenUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scaffoldState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScaffoldState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nc"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scaffoldState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scaffoldState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Button Clicked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click Me"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: We'll be using 'remember' which wraps a state object for the ScaffoldState into a value that persists after recompositions. If you want more details on that, ask me on &lt;a href="https://www.twitter.com/aniketSMK"&gt;Twitter&lt;/a&gt; I'll be happy to answer.&lt;/p&gt;

&lt;p&gt;Now we'll create a CoroutineScope for the SnackBar and launch it, in place of the log!&lt;/p&gt;

&lt;h1&gt;
  
  
  The Complete Code
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;MainScreenUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scaffoldState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScaffoldState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;snackbarCoroutineScope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberCoroutineScope&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nc"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scaffoldState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scaffoldState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;snackbarCoroutineScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;scaffoldState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snackbarHostState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showSnackbar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Button Clicked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click Me"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, finally it all comes down the line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;snackbarCoroutineScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;scaffoldState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snackbarHostState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showSnackbar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Button Clicked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SnackbarState is within the ScaffoldState we retrieved. The new CoroutineScope we created is used to launch the snackbar.&lt;/p&gt;

&lt;p&gt;Easy as pie! Once you know what's going on that is.&lt;/p&gt;




&lt;p&gt;I'm on the lookout for a Senior Android position with great customer impact, a great team and great compensation. Let me know if you're hiring! Also open to consulting contracts.&lt;/p&gt;

</description>
      <category>snackbar</category>
      <category>jetpackcompose</category>
      <category>kotlin</category>
      <category>android</category>
    </item>
    <item>
      <title>Notes on a Heap</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Sun, 09 Aug 2020 05:39:48 +0000</pubDate>
      <link>https://forem.com/aniketsmk/notes-on-a-heap-1gf8</link>
      <guid>https://forem.com/aniketsmk/notes-on-a-heap-1gf8</guid>
      <description>&lt;p&gt;As usual I learned about heaps from two places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vaidehi's &lt;a href="https://medium.com/basecs/learning-to-love-heaps-cef2b273a238"&gt;BaseCS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mitpress.mit.edu/books/introduction-algorithms-third-edition"&gt;Introduction to Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  What's a heap?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;A binary tree&lt;/li&gt;
&lt;li&gt;Parents are always greater than their children (max-heap) OR&lt;/li&gt;
&lt;li&gt;Parents are always smaller than their children (min-heap)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Implementation Notes:
&lt;/h1&gt;

&lt;p&gt;Instead of a node object structure, it's most useful to use a simple array to represent this.&lt;/p&gt;

&lt;p&gt;This is because we need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rapid access to the last element in the heap (which always happens to be the last element in the array)&lt;/li&gt;
&lt;li&gt;Easy ways to swap the &lt;em&gt;values&lt;/em&gt; of two nodes while leaving all their children the same.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the maths that puts this in order is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For a 0 indexed array&lt;/li&gt;
&lt;li&gt;The left child of an index is at 2i + 1&lt;/li&gt;
&lt;li&gt;The right child of an index is at 2i + 2&lt;/li&gt;
&lt;li&gt;You'd need the equation for the parent but it's best to calculate it from &lt;code&gt;2*parentIndex + 1 = childIndex&lt;/code&gt; to get &lt;code&gt;(childIndex - 1)/2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;As long as you keep the entire calculation in Int, your language will round it off appropriately whether it's actually the left child or not.&lt;/li&gt;
&lt;li&gt;Since you'd either end up with a .5 value if it was the right child, which rounds down to the correct parent index, or the actual parent index as an Integer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Kotlin Implementation
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Easier to use a mutableList and a recursive implementation.&lt;/li&gt;
&lt;li&gt;You'd need to use removeElementAt(size - 1) to get the last value to put at the root.&lt;/li&gt;
&lt;li&gt;I prefer implementing classes that handle generic values, so the MaxHeap takes a T&lt;/li&gt;
&lt;li&gt;However, the type given here has to be a Comparable so that &amp;gt; and &amp;lt; work. So that's the only limitation on the generic value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Functions:
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Insert
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Insert, always bubbles up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Memory Helper: "inserting is positive, going up is positive, they go together"&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Extract, you'd need to bubble down
The root is what you extract, which is the largest or smallest value in the heap.
The last element in the heap is then put at the root and bubbled down.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Memory Helper:
&lt;/h1&gt;

&lt;p&gt;"The whole point of the heap is to extract the min/max value and then the value you'd put in there is already at the top so you'd have to go down"&lt;/p&gt;

&lt;h1&gt;
  
  
  Useful property:
&lt;/h1&gt;

&lt;p&gt;Extracting or inserting always takes LogN time, you can the smallest or largest n elements by calling its extract over and over.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fun facts:
&lt;/h1&gt;

&lt;p&gt;The book uses 1 indexed arrays and Vaidehi uses 0 indexed arrays, this changes their equations for child nodes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code + Test
&lt;/h1&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>dsa</category>
      <category>datastructure</category>
      <category>heap</category>
      <category>binarytree</category>
    </item>
    <item>
      <title>The Simplest Recycler EmptyView</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Wed, 05 Aug 2020 08:24:41 +0000</pubDate>
      <link>https://forem.com/aniketsmk/the-simplest-recycler-emptyview-2p3f</link>
      <guid>https://forem.com/aniketsmk/the-simplest-recycler-emptyview-2p3f</guid>
      <description>&lt;p&gt;A recyclerview with something to show when it's empty is a pretty common pattern, many times we're tempted to do this in code.&lt;/p&gt;

&lt;p&gt;We're going to look at a better way to do than:&lt;br&gt;
Checking if the number of items in the adapter is zero and then show the empty view else, show the recyclerview.&lt;/p&gt;

&lt;p&gt;Here's the code, and it's all XML&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;No code required. This will show the recyclerview when items are present, and the progressbar in the center when it's not.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;A few key points&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The layout is a vertically oriented LinearLayout with only two items, the recyclerview and the container for the progressbar.&lt;/li&gt;
&lt;li&gt;The progressbar is the second item in this list.&lt;/li&gt;
&lt;li&gt;Recyclerview's widths and heights are always calculated from their children.
If there are no children, it sets itself to zero. When there are children, it actually follows the rest of the rules given to it like

&lt;code&gt;match_parent&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you look into the &lt;a href="https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java#3656"&gt;source code&lt;/a&gt; of the RecyclerView you'd see this line in onMeasure, which is what defines the dimens of the view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;mLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMeasuredDimensionFromChildren&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widthSpec&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;heightSpec&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So that's it! You can now get a clean empty view that naturally gets shoved under the recyclerview when there are items and you didn't one bit of Java/Kotlin code to do it yourself!&lt;/p&gt;

</description>
      <category>recyclerview</category>
      <category>android</category>
      <category>emptyview</category>
      <category>ui</category>
    </item>
    <item>
      <title>Dagger with a Hilt</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Fri, 24 Jul 2020 10:30:55 +0000</pubDate>
      <link>https://forem.com/aniketsmk/dagger-with-a-hilt-1k5g</link>
      <guid>https://forem.com/aniketsmk/dagger-with-a-hilt-1k5g</guid>
      <description>&lt;p&gt;AndroidEntryPoint is now quite a bit better and in general availability so we can now move to this method!&lt;/p&gt;

&lt;p&gt;This lets us specify the bare minimum to have a functional Dagger setup, with few drawbacks and get going really quickly with the code we care about.&lt;/p&gt;

&lt;p&gt;Looking to rapidly bootstrap a new app with Dagger and Hilt?&lt;br&gt;
Here are some steps to how it might practically be used. You could go in order to jump to the section you'd like.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup&lt;/li&gt;
&lt;li&gt;Create an Application class&lt;/li&gt;
&lt;li&gt;Let's get a ViewModel, but first..&lt;/li&gt;
&lt;li&gt;Creating a Retrofit Provider&lt;/li&gt;
&lt;li&gt;Creating an API interface for the actual call&lt;/li&gt;
&lt;li&gt;Creating concrete instances of the API &lt;/li&gt;
&lt;li&gt;Creating a Repository&lt;/li&gt;
&lt;li&gt;Finally the ViewModel&lt;/li&gt;
&lt;li&gt;Wrapping it up in the Activity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Basic Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;classpath "com.google.dagger:hilt-android-gradle-plugin:2.28-alpha"&lt;/code&gt; to your project level build.gradle (the one at your project root)&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;apply plugin: 'dagger.hilt.android.plugin'&lt;/code&gt; to the top of your app level build.gradle&lt;/li&gt;
&lt;li&gt;Ensure you have &lt;code&gt;apply plugin: 'kotlin-kapt'&lt;/code&gt; in your app level build.gradle as well&lt;/li&gt;
&lt;li&gt;Import the following at the app level build.gradle:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;implementation "com.google.dagger:hilt-android:2.28-alpha"&lt;br&gt;
kapt"com.google.dagger:hilt-android-compiler:2.28-alpha"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once you've gotten your setup ready, here's what you do.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create an Application class
&lt;/h2&gt;

&lt;p&gt;Then annotate it with &lt;code&gt;@HiltAndroidApp&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@HiltAndroidApp&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoApplication&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Don't forget to add the classname of your application to the Manifest!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt;
        &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;".DemoApplication"&lt;/span&gt;
        &lt;span class="na"&gt;android:allowBackup=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Let's get a ViewModel, but first..
&lt;/h1&gt;

&lt;p&gt;Since it's only going to be useful with a repo and some Api passed in:&lt;/p&gt;

&lt;p&gt;We're going to be using the standard separation of concerns which means we're going to need three classes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The provider for the Retrofit instance&lt;/li&gt;
&lt;li&gt;The API interface for the network call to be made by retrofit&lt;/li&gt;
&lt;li&gt;The repository which will take in an instance of the created API and be responsible for exposing it to the ViewModel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're going to create them in that order only because the app wouldn't compile in an intermediate state otherwise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Retrofit Provider
&lt;/h3&gt;

&lt;p&gt;I'll get to what &lt;code&gt;@ApplicationComponent&lt;/code&gt; is and why the module is an &lt;code&gt;object&lt;/code&gt; along with why this particular provider is marked &lt;code&gt;@Singleton&lt;/code&gt; right after showing you code for this module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.Module&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.Provides&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.hilt.InstallIn&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.hilt.android.components.ApplicationComponent&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.reactivex.schedulers.Schedulers&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;okhttp3.OkHttpClient&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;retrofit2.Retrofit&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.inject.Singleton&lt;/span&gt;

&lt;span class="nd"&gt;@InstallIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApplicationComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Module&lt;/span&gt;
&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;RetrofitModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Singleton&lt;/span&gt;
    &lt;span class="nd"&gt;@Provides&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getRetrofit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Retrofit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Retrofit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://something.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCallAdapterFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RxJava2CallAdapterFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@Provides&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since we only ever want one instance of Retrofit (to improve connection pooling) this is a Singleton provider.&lt;br&gt;
It might feel odd having a default okhttp client provided but this is often modified with interceptors.&lt;/p&gt;

&lt;p&gt;This is installed in the &lt;code&gt;Application&lt;/code&gt; &lt;a href="https://developer.android.com/training/dependency-injection/hilt-android#component-lifetimes"&gt;component&lt;/a&gt; since we want the retrofit instance to not only be unique for the entire app, but also at the highest level in the dependency graph so it's available to all other modules.&lt;/p&gt;

&lt;p&gt;This follows the standard practise of Modules being Singletons (via the object notation) for faster runtime performance. &lt;/p&gt;

&lt;p&gt;Note: Since Dagger 2.25, we no longer need to annotate the functions JvmStatic.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating an API interface for the actual call
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.reactivex.Observable&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;retrofit2.http.GET&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SomethingApi&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"widgets/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getWidgets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The pretend API has an endpoint called widgets and we're going to get ourselves some widgets!&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating concrete instances of the API
&lt;/h3&gt;

&lt;p&gt;Since it requires retrofit to create concrete instances of the API, we're going to need a module that will manage that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.Module&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.Provides&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.hilt.InstallIn&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.hilt.android.components.ActivityRetainedComponent&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;retrofit2.Retrofit&lt;/span&gt;

&lt;span class="nd"&gt;@InstallIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ActivityRetainedComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Module&lt;/span&gt;
&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;ApiModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Provides&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getSomethingApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retrofit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Retrofit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;SomethingApi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;retrofit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SomethingApi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that is in an &lt;code&gt;ActivityRetainedComponent&lt;/code&gt; since it's intended to be used by a ViewModel that will itself be preserved on activity rotation. The only difference between the &lt;code&gt;ActivityRetainedComponent&lt;/code&gt; and the &lt;code&gt;ActivityComponent&lt;/code&gt; is that the provided object in the first scope is 'retained' or kept, through configuration changes. See &lt;a href="https://developer.android.com/training/dependency-injection/hilt-android#component-lifetimes"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Repository
&lt;/h3&gt;

&lt;p&gt;This repo will abstract away the network and DB api's for the ViewModel&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.reactivex.Observable&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.inject.Inject&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainRepo&lt;/span&gt; &lt;span class="nd"&gt;@Inject&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;somethingApi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SomethingApi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getWidgets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;somethingApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getWidgets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Finally the ViewModel
&lt;/h3&gt;

&lt;p&gt;ViewModel Factories no longer need to be created since the Hilt compiler will do that bit of code generation.&lt;/p&gt;

&lt;p&gt;You'll need &lt;code&gt;implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"&lt;/code&gt; for the &lt;code&gt;@ViewModelInject&lt;/code&gt; annotation.&lt;/p&gt;

&lt;p&gt;Also &lt;code&gt;kapt "androidx.hilt:hilt-compiler:1.0.0-alpha01"&lt;/code&gt; for the hilt compiler that will actually generate the ViewModel factories for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.hilt.lifecycle.ViewModelInject&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.lifecycle.ViewModel&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainViewModel&lt;/span&gt; &lt;span class="nd"&gt;@ViewModelInject&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mainRepo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MainRepo&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Wrapping it up in the Activity
&lt;/h1&gt;

&lt;p&gt;Now we're ready to use this ViewModel in the Activity and it's done with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.os.Bundle&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.activity.viewModels&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.appcompat.app.AppCompatActivity&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dagger.hilt.android.AndroidEntryPoint&lt;/span&gt;

&lt;span class="nd"&gt;@AndroidEntryPoint&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mainViewModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MainViewModel&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;viewModels&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To get the &lt;code&gt;viewModels&lt;/code&gt; delegate, you'll need to add the activity or fragment kotlin extension libraries depending on where you want to use it.&lt;br&gt;
That's &lt;code&gt;implementation "androidx.activity:activity-ktx:1.2.0-alpha06"&lt;/code&gt; or&lt;br&gt;
&lt;code&gt;implementation "androidx.fragment:fragment-ktx:1.3.0-alpha06"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it!&lt;br&gt;
You're ready to use dependency injected viewmodels!&lt;/p&gt;

&lt;p&gt;If you wanted to use this with fragments and want to share the activity's viewmodel with them, use &lt;code&gt;activityViewModels&lt;/code&gt; instead of viewmodels in them.&lt;/p&gt;

&lt;p&gt;Check back in later to see how to use this with navigation components and with testing.&lt;/p&gt;




&lt;p&gt;Looking to get your devs up to speed on the latest techniques to boost productivity and your time to market? Reach out to me for consulting at &lt;a href="mailto:consulting@aniketkadam.com"&gt;consulting@aniketkadam.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dagger</category>
      <category>android</category>
      <category>dependency</category>
      <category>injection</category>
    </item>
    <item>
      <title>Intro to Testing: Why Test</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Thu, 09 Jul 2020 14:15:52 +0000</pubDate>
      <link>https://forem.com/aniketsmk/intro-to-testing-why-test-ag2</link>
      <guid>https://forem.com/aniketsmk/intro-to-testing-why-test-ag2</guid>
      <description>&lt;p&gt;When you write a feature, how do you know it works?&lt;br&gt;
A lot of people, will run their code, and if you're an Android dev, you see it running on the phone and now you know if it works.&lt;/p&gt;

&lt;p&gt;For Android in particular, this takes quite a while to do.&lt;br&gt;
Have you ever sat down, and timed how long it takes from the time you write some function and hit run, to the time it actually starts up on a phone?&lt;br&gt;
How many times do you do that procedure when writing code? How many times a day do you do it? Sure instant run might help a lot of times, but what if the thing you're checking requires you to go a bit deeper into the app? Each trial run could easily take 5 minutes and then if you just tried something 6 times, you've spent half an hour of your day on it.&lt;/p&gt;

&lt;h1&gt;
  
  
  What if you could save all that time?
&lt;/h1&gt;

&lt;p&gt;Testing has become associated with something complex but nothing could be further from the truth. Yes, you will be learning new techniques and learning to think a bit differently but the end result is that your work will be easier!&lt;/p&gt;

&lt;p&gt;You're going to spend less time, to get more things done and you'll be more confident that things are working the way they should.&lt;/p&gt;

&lt;h1&gt;
  
  
  We all test our code, the only difference is whether it takes milliseconds or minutes.
&lt;/h1&gt;

&lt;p&gt;I use testing for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Faster development.&lt;/li&gt;
&lt;li&gt;A measure of confidence in its correctness.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll take a look at how to do this next time in this series, alongside when to do it, what to test, what not to test, mental models and benefits you get from it.&lt;/p&gt;

&lt;p&gt;Meanwhile, take a look at one of the central concepts in testing that I wrote about &lt;a href="https://dev.to/aniketsmk/making-your-code-more-flexible-dagger-prelude-part-0-23l"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If your team could use some help, or would like getting things more often and faster with less time; I consult on Android. Reach out to me at &lt;a href="mailto:consulting@aniketkadam.com"&gt;consulting@aniketkadam.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>android</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Android Sorting CheatSheet</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Wed, 13 May 2020 10:44:54 +0000</pubDate>
      <link>https://forem.com/aniketsmk/android-sorting-cheatsheet-5blb</link>
      <guid>https://forem.com/aniketsmk/android-sorting-cheatsheet-5blb</guid>
      <description>&lt;h1&gt;
  
  
  For Kotlin
&lt;/h1&gt;

&lt;p&gt;If there's just one value to compare, then the following can be used&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sortedBy&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The two methods are used to compare the items in the list. If the first one returns equal, then the second will take over&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;arrangeNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sortedWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compareBy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  For Java
&lt;/h1&gt;

&lt;p&gt;When using java, a comparator object has to be created, these can be chained with &lt;code&gt;thenBy&lt;/code&gt; calls.&lt;br&gt;
A stream still needs to be created and collected for the result to be calculated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;arrangeNames&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sizeComparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;comparing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;String:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;thenBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;String:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;sorted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sizeComparator&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>sorting</category>
      <category>android</category>
      <category>java8</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Effective Git, zero to max in small steps: First Steps</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Tue, 28 Apr 2020 08:17:49 +0000</pubDate>
      <link>https://forem.com/aniketsmk/effective-git-zero-to-max-in-small-steps-first-steps-enk</link>
      <guid>https://forem.com/aniketsmk/effective-git-zero-to-max-in-small-steps-first-steps-enk</guid>
      <description>&lt;p&gt;Git probably has the highest ratio of misunderstanding/usage ratios of any software tool. It's also one with a tremendous variety of valid usages that look very little like each other.&lt;/p&gt;

&lt;p&gt;I'm going to walk through some of its strengths and one good thing to use it for.&lt;/p&gt;

&lt;p&gt;Ostensibly, git is a tool to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep track of changes to a codebase&lt;/li&gt;
&lt;li&gt;Synchronize, and provide tools to synchronize, changes to the same file that may sometimes conflict.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're using git for open source work, you need to consider that the credentials you add to it are public too so you need some extra strategies to deal with that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and Intro
&lt;/h2&gt;

&lt;p&gt;If you'd like a GUI, I'd recommend whatever's built into your code editor. vcode and Android Studio both have quite decent git clients.&lt;/p&gt;

&lt;p&gt;For an advanced usage like selective stage ( partially committing changes in one file ) I very highly recommend git-cola.&lt;/p&gt;

&lt;p&gt;Knowledge of the commandline is very useful if you've totally broken something ( which happens on an uncommon but not rare basis ), and to better understand some cryptic errors you might get from the GUIs sometimes.&lt;/p&gt;

&lt;p&gt;As far as possible, I'll try to remain tool agnostic and use only git terms, but also tell you things in terms of the commandline.&lt;/p&gt;

&lt;p&gt;Note: Since git depends on a local database in the .git folder, changes made from any tool are generally visible in any other tool ( except Android Studio's stages ). So feel free to mix and match as you like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concepts
&lt;/h2&gt;

&lt;p&gt;For the barest use of git, you only need to know two commands.&lt;br&gt;
&lt;code&gt;stage&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;code&gt;commit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A commit is a group of 'changes' that you save at once into git. There's a reason I said changes and not files but we'll get to that later. You can think of a change as one line of text that's been added or deleted.\&lt;/p&gt;

&lt;p&gt;Since we can add multiple changes at once, to tell git what changes we want to group together, we &lt;code&gt;stage&lt;/code&gt; them.&lt;br&gt;
Staging tells git that this version of the change is something you're adding to a list that you might want to save or &lt;code&gt;commit&lt;/code&gt; together.&lt;/p&gt;

&lt;p&gt;If you try to &lt;code&gt;commit&lt;/code&gt; without &lt;code&gt;stage&lt;/code&gt;, git will do nothing. Since the list of changes that you wanted to save or &lt;code&gt;commit&lt;/code&gt; is empty.&lt;/p&gt;

&lt;p&gt;So let's say you create a new folder and open a terminal inside it.&lt;br&gt;
You initialize git in that folder, to track changes in that folder, with the command&lt;br&gt;
&lt;code&gt;git init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's say you create a text file in there called Readme.txt, you can see how git sees it with&lt;br&gt;
&lt;code&gt;git status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that you can see that git knows a new file is in there, you can save it into git with&lt;br&gt;
&lt;code&gt;git add Readme.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Another thing you could do, is &lt;code&gt;stage&lt;/code&gt; all the files in the folder with&lt;br&gt;
&lt;code&gt;git add .&lt;/code&gt;&lt;br&gt;
Notice the dot at the end, this tells git to add whatever files it sees &lt;em&gt;in this folder&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you've got the files staged, you can commit!&lt;/p&gt;

&lt;p&gt;The barest command (which you should never run actually) you need for this is&lt;br&gt;
&lt;code&gt;git commit&lt;/code&gt; and you'll see that it's done.&lt;/p&gt;

&lt;p&gt;Why shouldn't we just commit (save changes) like this? Because no one would know what changed in with this set of changes.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;high-level&lt;/em&gt; description message should always be provided with every commit that says &lt;em&gt;why&lt;/em&gt; it changed along with an &lt;em&gt;overview&lt;/em&gt; of what.&lt;br&gt;
So a good description message could be "Added readme"&lt;/p&gt;

&lt;p&gt;Here's what the commit command looks like when you add a message that explains the change as well.&lt;br&gt;
&lt;code&gt;git commit -m "Added readme"&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;That's it for this intro!&lt;br&gt;
Next time, we'll look into branching and merging. What those are and why you might do them.&lt;/p&gt;

</description>
      <category>git</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>newbie</category>
    </item>
    <item>
      <title>Tips to Writing Tech Talks/Blog posts</title>
      <dc:creator>Aniket Kadam</dc:creator>
      <pubDate>Sun, 09 Feb 2020 15:26:50 +0000</pubDate>
      <link>https://forem.com/aniketsmk/tips-to-writing-tech-talks-blog-posts-1jh9</link>
      <guid>https://forem.com/aniketsmk/tips-to-writing-tech-talks-blog-posts-1jh9</guid>
      <description>&lt;h2&gt;
  
  
  Should You Do a Talk?
&lt;/h2&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;An unreserved, no-background-needed, yes. Writing and Speaking is how you show to other people &lt;em&gt;not only&lt;/em&gt; that you know your stuff but that you can communicate it effectively.&lt;/p&gt;

&lt;p&gt;These are vital skills not only for your work, but to help you in your next job search as well.&lt;/p&gt;

&lt;p&gt;I guarantee that what you know and the mental model you have for what you know, is going to help someone. So please write it even if it's been written about before.&lt;/p&gt;

&lt;p&gt;It's about writing/speaking about it in &lt;em&gt;your&lt;/em&gt; own voice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stagefright
&lt;/h2&gt;

&lt;p&gt;You can stare straight at the back of the room and pretend you're giving a talk to a large empty room, bonus, it looks like you're confidently looking right at the crowd! If you're nervous, stack the front row or middle with your friends whose job is to nod and smile and thumb's up and you're going to look right at them as you give your talk.&lt;/p&gt;

&lt;p&gt;Another technique which I picked up later is best explained via a quote from the movie Bohemian Rhapsody, about the lead singer of a band called Queen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mary Austin: What's it like, singing for all those people?&lt;/li&gt;
&lt;li&gt;Freddie Mercury: When I know they're listening, when I know I really have them, I couldn't sing off-key if I tried. I am exactly the person I was always meant to be. I'm not afraid of anything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The audience is your friend. They want you to do well. You're chatting to them about something that was fun enough for you want to tell other about it and they're eager to hear it. You're all going to love this :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do a talk about?
&lt;/h2&gt;

&lt;p&gt;Whatever you do in your daily work! Have you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Come up with a nice solution for something?&lt;/li&gt;
&lt;li&gt;Gotten through a painful setup of a library or a dev environment?&lt;/li&gt;
&lt;li&gt;Learned something that was difficult &lt;em&gt;for you&lt;/em&gt; and now have an insight that can explain it in a simpler way?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these ideas are what you know really well and have spent some time on. You could save somebody else that same time by doing a talk/blog post on it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Talk Outline
&lt;/h2&gt;

&lt;p&gt;Whatever you want to talk about, what would be the broad headings of how you'd explain it to someone?&lt;/p&gt;

&lt;p&gt;If you consider a book on the topic, what would be the chapter headings? &lt;a href="https://dev.to/aniketsmk/how-to-write-code-beyond-your-ability-e31"&gt;Write these down&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you've got your chapter points, you can look at them overall and get an idea of how the talk would go and how you'd like to present it.&lt;/p&gt;

&lt;p&gt;Keep adding bullet points, like sub-chapters about the ideas you want to discuss within the main chapter. These may eventually be a slide each, or just points on one slide for the chapter!&lt;/p&gt;

&lt;p&gt;It's a good idea to give people a reason to care, tell them about the biggest benefits of your ideas in the first 2 minutes of the talk.&lt;/p&gt;

&lt;p&gt;Don't talk about setup unless that was the hard part for you, you can link people to the setup and that's usually enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making your slides.
&lt;/h2&gt;

&lt;p&gt;Don't have a huge amount of text on your slide. The less you have, the better. Nobody can read and follow what you're saying at the same time.&lt;/p&gt;

&lt;p&gt;At most, do bullet points. If you do have bullet points, animate them in when you reach them, don't display them all at once. Most slide making software have something for this including Google Slides which is what I use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;

&lt;p&gt;If you have code, only include the section relevant to the concept you're trying to explain.&lt;/p&gt;

&lt;p&gt;You can add a github link for the full detail and don't overwhelm the people with large classes or waay too many functions.&lt;/p&gt;

&lt;p&gt;A good rule of thumb is, if it's too much code to comfortably read as a slide from across the room you're sitting in, it's too much code for a slide.&lt;/p&gt;

&lt;p&gt;Write your code in Android Studio, use Roman Nurik's &lt;a href="https://romannurik.github.io/SlidesCodeHighlighter/"&gt;Slides Code Highlighter&lt;/a&gt; to give you the syntax colouring in Google Slides.&lt;/p&gt;

&lt;p&gt;Another way to do this is with &lt;a href="https://carbon.now.sh/"&gt;Carbon&lt;/a&gt; which will give you pngs or svgs of your code but when you make the inevitable mistakes, you can't edit that image!&lt;/p&gt;

&lt;p&gt;That's why I prefer getting the colour formatted text and running it through the slides code highlighter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Places to Speak
&lt;/h2&gt;

&lt;p&gt;I'd always suggest looking into your local meetups. You can usually find these on meetup.com or asking about it on twitter or asking your other colleagues what they know about.&lt;/p&gt;

&lt;p&gt;The huge famous meetups you can always find on google.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying To CFPs (call for papers)
&lt;/h2&gt;

&lt;p&gt;Ideally you should do this before you've even written your talk. Most abstract applications will end in rejection. &lt;a href="https://www.ted.com/talks/jia_jiang_what_i_learned_from_100_days_of_rejection?language=en"&gt;Get used to rejection&lt;/a&gt;, it's also really good for you.&lt;/p&gt;

&lt;p&gt;By writing short abstracts, an enticing paragraph about what your talk could be about and what people could expect to learn from it, you'll minimize the time you take to apply to conferences and increase your chances of being accepted at one.&lt;/p&gt;

&lt;p&gt;You can absolutely write a talk about anything you've done, I always feel like there's not enough there to fill a 40 minute slot and then when I sit to make the slides I realise there's waaaay too much to cover in just one talk!&lt;/p&gt;

&lt;p&gt;And if the idea is rejected and you really want to do it anyway, consider making it a blog post!&lt;/p&gt;

&lt;h2&gt;
  
  
  Backups
&lt;/h2&gt;

&lt;p&gt;I use Google Slides and the &lt;a href="https://support.google.com/docs/answer/6388102?co=GENIE.Platform%3DDesktop&amp;amp;hl=en"&gt;Slides Offline&lt;/a&gt; Chrome Extension so that I have the slides available even if the internet is spotty.&lt;/p&gt;

&lt;p&gt;I also create a public sharing link and put it into bit.ly with a nice readable name and keep that as a Whatsapp Message or emailed to someone so that I can refer to that in case you can't use your machine at all for whatever reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling The Audience
&lt;/h2&gt;

&lt;p&gt;It's always best if you can involve the audience somehow. Whether that's making them laugh, or guiding them so that they can get an intuitive feel for what's next and asking if they can fill-in-the-blanks or asking for their own experience of things. The more you give the audience a chance to speak, the more they'll connect to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Ideas
&lt;/h2&gt;

&lt;p&gt;Once you've given a few talks and are familiar with the idea. Be aware that this isn't a college lecture or a dull presentation.&lt;/p&gt;

&lt;p&gt;Speaking is a performance. You're an actor on a stage and your job is hold the attention of these people and give them something to remember. How you achieve that is usually by amping up either your natural personality or whatever you find entertaining to see.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;




&lt;p&gt;Speaking is what Donn Felker calls &lt;a href="https://www.donnfelker.com/the-single-best-thing-you-can-do-for-your-career/"&gt;"The Single Best Thing You Can Do For Your Career"&lt;/a&gt; and I'm very inclined to agree.&lt;/p&gt;

&lt;p&gt;Good luck, you can do this and you're going to get better with practise.&lt;/p&gt;

</description>
      <category>technical</category>
      <category>speaking</category>
      <category>talks</category>
      <category>howto</category>
    </item>
  </channel>
</rss>
