<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Art and science of writing good code]]></title><description><![CDATA[Art and science of writing good code]]></description><link>https://maxkim.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 07:49:52 GMT</lastBuildDate><atom:link href="https://maxkim.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Full Guide to Testing Android Applications in 2022]]></title><description><![CDATA[Testing is quite a fascinating topic in software development. On the one hand, writing tests takes time, and it might not feel as rewarding - you cannot show a test to a client as you can a new feature. On the other hand, writing tests is an integral...]]></description><link>https://maxkim.dev/full-guide-to-testing-android-applications-in-2022</link><guid isPermaLink="true">https://maxkim.dev/full-guide-to-testing-android-applications-in-2022</guid><category><![CDATA[THW Mobile Apps]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Fri, 13 May 2022 10:38:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652343671311/ElJ-dtU-y.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Testing is quite a fascinating topic in software development. On the one hand, writing tests takes time, and it might not feel as rewarding - you cannot show a test to a client as you can a new feature. On the other hand, writing tests is an integral part of a project and shouldn't be treated less seriously than the code that makes the wheels turn. </p>
<p>Apart from actually testing the code functionality, there are many other benefits to writing tests. Tests can act as supplementary documentation that explains the expected behavior of the software. Tests can be a safety net and confidence boosters during complicated refactors and rewrites. Moreover, tests - or the inability to write them - can shine a light on architectural flaws, inciting developers to step up their game and write better code.</p>
<p>That said, even though we will talk a bit about theory, the main goal of this article is to see how Android testing works <em>in practice</em>. We will take a small sample project without any tests and, in the end, have a fully tested application.</p>
<blockquote>
<p>Since we will be covering all aspects of testing an Android application, this article is not meant to be consumed in one sitting. There is too much information for that, especially for junior developers. The goal of this article is to create a comprehensive guide to Android testing, which can be studied and referred to as needed.</p>
</blockquote>
<h1 id="heading-about-the-sample-project">About the sample project</h1>
<p>The project for today's purposes will be a sample app named Boredom Buster. </p>
<p><strong>The source code can be found on <a target="_blank" href="https://github.com/mkims/boredom-buster">GitHub</a>.</strong> </p>
<p>This app uses the free <a target="_blank" href="https://www.boredapi.com/">BoredAPI</a> to fetch a random activity and allows the user to save this activity to a database as a favorite for later browsing.</p>
<p>The app consists of two screens - an activity screen where the user can generate a random activity and save it to a database and a second screen where the user can see a list of all saved activities and delete them if they wish.</p>
<p>I have used the MVVM design pattern for the app with the following tech stack:</p>
<ul>
<li>Jetpack Compose with Navigation</li>
<li>Jetpack Lifecycle Components</li>
<li>Retrofit with Moshi converter</li>
<li>Room</li>
<li>Hilt</li>
</ul>
<p>If you would like to follow along with this article, the repository has a branch <code>start</code>, which doesn't have any tests and will be our starting point. The branch <code>finish</code> contains all the tests that we will write in this article.</p>
<blockquote>
<p>Note: We will be using the new Coroutines Test API, which was released in <code>kotlinx.coroutines 1.6.0</code>.</p>
</blockquote>
<h1 id="heading-making-your-code-testable">Making your code testable</h1>
<p>This will be a very practical article, but before we start, I would like to spend a few moments on a topic that can't be ignored when talking about testing software.</p>
<p>In most cases, writing tests should be straightforward. If you cannot find an easy way to test your code, chances are that your code has some structural flaws.</p>
<p>That is where architecture comes in. </p>
<p>Today we will not focus on architecture, but keep in mind that it is an integral part of writing good tests.</p>
<p>If you are not familiar with the Android App architecture, a good place to start is <a target="_blank" href="https://developer.android.com/topic/architecture">the official guide to app architecture</a> from Google. However, for a more advanced understanding of architecture, I strongly recommend studying Uncle Bob's Clean Architecture approach. His <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">blog post</a> on the topic was so popular that Uncle Bob wrote a whole book on the subject, and I consider it a must-read for any software developer.</p>
<p>The app we will be testing today uses a Clean Architecture approach adapted for Android.</p>
<h1 id="heading-writing-unit-tests">Writing Unit tests</h1>
<p>On that note, let's open up our project and start writing some tests.</p>
<p>First, we will tackle Unit tests that test individual small parts of our application - methods, functions, and classes.</p>
<h2 id="heading-testing-viewmodels-with-stateflow">Testing ViewModels with StateFlow</h2>
<p>In Android, one of the most important parts to test is the ViewModels, and that is where we will start.</p>
<p>Our project has two ViewModels - one for the Activity screen (I don't see any reason why this can be confusing to Android developers, right?) that is responsible for fetching and displaying a random activity, and one for the Favorites screens displaying a list of saved activities.</p>
<p>Let's first open up <code>NewActivityViewModel</code> and look at its structure.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652289982349/RDUH9fhIK.png" alt="NewActivityViewModel_structure.png" /></p>
<p>We have two public methods:</p>
<ul>
<li><code>loadNewActivity(): Unit</code> - a method that fetches a random activity from the API and updates the UI state;</li>
<li><code>setIsFavorite(Activity, Boolean): Unit</code> - a method that either saves an activity to the database or deletes it.</li>
</ul>
<p>We also have a publicly exposed <code>StateFlow&lt;NewActivityUiState&gt;</code>, which emits the current UI state for the Activity screen.</p>
<blockquote>
<p>Note: We are using a <code>StateFlow</code> in this <code>ViewModel</code>, but for the sake of covering more testing examples, the <code>FavoritesViewModel</code> exposes its UI state via a <code>LiveData</code>.</p>
</blockquote>
<p>One important thing to note here is that <code>NewActivityViewModel</code> also calls <code>loadNewActivity()</code> in its <code>init()</code> block to immediately display a random activity to the user.</p>
<h3 id="heading-test-scenarios">Test scenarios</h3>
<p>Given that, here are the scenarios we would like to test to make sure our ViewModel works correctly:</p>
<ol>
<li>When creating a <code>NewActivityViewModel</code>, the initial UI state is <code>Loading</code>;</li>
<li>Creating a <code>NewActivityViewModel</code> triggers the emission of a new <code>Success</code> UI state;</li>
<li>Creating a <code>NewActivityViewModel</code> triggers the emission of a new <code>Error</code> UI state in case of error;</li>
<li>If Activity is already saved, the UI state's <code>isFavorite</code> is set to <code>true</code>;</li>
<li>Calling <code>loadNewActivity()</code> successfully reloads the existing UI state with a new activity;</li>
<li>Calling <code>setIsFavorite(activity, true)</code> calls <code>SaveActivity</code> use case;</li>
<li>Calling <code>setIsFavorite(activity, false)</code> calls <code>DeleteActivity</code> use case.</li>
</ol>
<h3 id="heading-creating-a-test">Creating a test</h3>
<p>To create a test, you can either create a test file manually or make an Android Studio generate one for you.</p>
<p>To generate a test, you can press <code>Alt + Insert</code> on Windows or <code>Cmd + N</code> on Mac anywhere in the target file to open the <code>Generate</code> popup and select <code>Test</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652290155084/ANU2cRcRb.png" alt="Generate_test.png" /></p>
<p>This will open the Create Test popup:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652290190247/rCSdhnzHH.png" alt="Generate_test_popup.png" /></p>
<p>Projects generated by Android Studio automatically have the necessary dependencies to run tests with <code>JUnit4</code>, so we will use that. <code>JUnit5</code> is not fully supported for Android and requires some more setting up, so we will ignore it. <code>JUnit4</code> is more than enough for our testing purposes.</p>
<p>There are some other options that this popup allows us to select, but we will ignore them for now and do everything manually as we see fit.</p>
<p>Clicking <code>OK</code> will prompt us to choose a destination directory:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652290220897/_Sa47OCxB.png" alt="choose_destination_directory.png" /></p>
<p>We have two options where to put our new test:</p>
<ul>
<li><code>androidTest</code> - a directory for <em>instrumented</em> Android tests, which run on either a physical or emulated Android device. This directory is for tests that depend on the Android framework to run. Most commonly those are UI tests or database tests.</li>
<li><code>test</code> - a directory for <em>local</em> unit tests or integrations tests that don't require the Android framework to run.</li>
</ul>
<p>With that in mind, we will be using the <code>test</code> directory since we don't need anything from the Android framework.</p>
<blockquote>
<p>Note: This is one of the main reasons why your ViewModels should not depend on Android <code>Context</code>. But there are also other considerations. Here <a target="_blank" href="https://medium.com/androiddevelopers/locale-changes-and-the-androidviewmodel-antipattern-84eb677660d9">is a good article</a> for further research.</p>
</blockquote>
<p>Clicking <code>OK</code> will generate or new test class, which is quite barebones for now, but we will create a separate test for every scenario outlined above.</p>
<p>In <code>JUnit</code> you create a test by annotating the test method with a <code>@Test</code> annotation.</p>
<p>Also, naming your test methods can be different from naming regular methods, depending on the convention you prefer. It is a good practice to write explicit method names, describing the expected behavior of the test. It also acts as complementary documentation for your code.</p>
<p>In Kotlin, we can use backticks to write method names in “plain text", which I prefer for naming tests.</p>
<p>However, there is a catch. Using this kind of naming is not allowed in Android projects. Therefore, if you want to use the same naming convention in your <code>test</code> and <code>androidTest</code> folders, you should probably stick with the regular naming.</p>
<p>That said, to illustrate that this is also a very popular approach in testing, we will use this naming in our non-Android tests.</p>
<p>With that in mind, let's create a test for the first scenario:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel exposes loading ui state`<span class="hljs-params">()</span></span> {

}
</code></pre>
<p>The tests usually follow the <code>AAA</code> pattern, which stands for <code>Arrange</code> - <code>Act</code> - <code>Assert</code>.</p>
<p>In this first scenario, we won't have an <code>Act</code> part since we will be testing the initial UI state immediately after creating the <code>NewActivityViewModel</code>.</p>
<p>However, we cannot just create an instance of <code>NewActivityViewModel</code> since it depends on a bunch of use cases. In this test, we are focusing on the <code>NewActivityViewModel</code> class only and don't care about all other parts of the app and how our app interacts with them. We will test that later with <em>integration tests,</em> which, as the name suggests, are meant to test integration between different components.</p>
<h3 id="heading-fakes-vs-mocks">Fakes vs. Mocks</h3>
<p>There are two common ways to solve this problem - by either using <strong><em>fakes</em></strong> or <strong><em>mocks</em></strong>. <strong><em>Fakes</em></strong> are working implementations of dependencies that are written with testing in mind, while <strong><em>mocks</em></strong> are test doubles that can be programmed to behave as you like and require a mocking framework, such as Mockito. </p>
<p>It is always a hot topic which approach is better. However, it is important to highlight that both approaches have pros and cons.</p>
<p>I prefer to use <strong><em>fakes</em></strong> as much as possible. I mainly use <strong><em>mocks</em></strong> when I test the number or order of interactions, which is much easier to do with <strong><em>mocks</em></strong>. In general, being too dependent on <strong><em>mocks</em></strong> can make you miss opportunities to have better integration tests when testing how multiple components work together. Or even highlight flaws in the architecture if your components depend on concrete implementations and it is not possible to create a <strong><em>fake</em></strong>. </p>
<blockquote>
<p>Your components <em>should be decoupled</em> for cleaner code and easier testing. In most cases, components should depend on interfaces, not concrete implementations.</p>
</blockquote>
<h3 id="heading-creating-fake-dependencies"><strong>Creating fake dependencies</strong></h3>
<p>We will discuss how to use both fakes and mocks in this article, but let's start with fakes since they don't require additional dependencies and are also <a target="_blank" href="https://developer.android.com/training/testing/fundamentals/test-doubles">recommended by Google</a>.</p>
<p>We will be reusing our fakes, so let's create a new package <code>eu.maxkim.boredombuster.activity.fake</code>, where we will put all our fakes.</p>
<p>To test our <code>ViewModel</code> we will only need fake use cases, so let’s put all of them together in a new package <code>.fake.usecase</code>.</p>
<p>First we need a fake <code>GetRandomActivity</code> use case, so let's create a new class <code>FakeGetRandomActivity</code>, which implements that interface.</p>
<p>Here is our newly created fake:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeGetRandomActivity</span> : <span class="hljs-type">GetRandomActivity {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: Result&lt;Activity&gt; {
        TODO(<span class="hljs-string">"Not yet implemented"</span>)
    }
}
</code></pre>
<p>As you can see, since the data comes from the network, our use case returns a wrapper <code>Result&lt;T&gt;</code>, which can either be a <code>Success</code> or <code>Error</code>. Naturally, we would want to test both those scenarios, so let's make sure our fake supports that. The easiest way to implement that is to just pass a <code>Boolean</code> argument in a constructor, which will change the behavior of our fake:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeGetRandomActivity</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> isSuccessful: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">true</span>
) : GetRandomActivity {
    ...
}
</code></pre>
<p>With that out of the way, we will also need some dummy test objects to play around with in our tests. To make things cleaner, let's create a new <code>TestModels.kt</code> file to store them.</p>
<p>For now let's add two test activities:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//TestModels.kt</span>
<span class="hljs-keyword">val</span> activity1 = Activity(
    name = <span class="hljs-string">"Learn to dance"</span>,
    type = Activity.Type.Recreational,
    participantCount = <span class="hljs-number">2</span>,
    price = <span class="hljs-number">0.1f</span>,
    accessibility = <span class="hljs-number">0.2f</span>,
    key = <span class="hljs-string">"112233"</span>,
    link = <span class="hljs-string">"www.dance.com"</span>
)

<span class="hljs-keyword">val</span> activity2 = Activity(
    name = <span class="hljs-string">"Pet a dog"</span>,
    type = Activity.Type.Relaxation,
    participantCount = <span class="hljs-number">1</span>,
    price = <span class="hljs-number">0.0f</span>,
    accessibility = <span class="hljs-number">0.1f</span>,
    key = <span class="hljs-string">"223344"</span>,
    link = <span class="hljs-string">"www.dog.com"</span>
)
</code></pre>
<p>Now we can finish our fake: </p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeGetRandomActivity</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> isSuccessful: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">true</span>
) : GetRandomActivity {

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: Result&lt;Activity&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> (isSuccessful) {
            Result.Success(activity1)
        } <span class="hljs-keyword">else</span> {
            Result.Error(RuntimeException(<span class="hljs-string">"Boom..."</span>))
        }
    }
}
</code></pre>
<p>Another fake that we will use in the first test scenario is <code>IsActivitySaved</code> use case.</p>
<p>When getting a random activity from API, we use this use case to check whether or not the user has already saved this activity to display its state correctly.</p>
<p>Later on, we will be testing whether or not our ViewModel correctly displays the favorite status, so we will make this fake flexible as well:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeIsActivitySaved</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> isActivitySaved: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">false</span>
) : IsActivitySaved {

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">(key: <span class="hljs-type">String</span>)</span></span>: <span class="hljs-built_in">Boolean</span> {
        <span class="hljs-keyword">return</span> isActivitySaved
    }
}
</code></pre>
<p>We won't use the two remaining use cases in the first test scenario, so let's just create them without any logic and return to them when we need them:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeSaveActivity</span> : <span class="hljs-type">SaveActivity {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">(activity: <span class="hljs-type">Activity</span>)</span></span> {
        TODO(<span class="hljs-string">"Not yet implemented"</span>)
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeDeleteActivity</span> : <span class="hljs-type">DeleteActivity {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">(activity: <span class="hljs-type">Activity</span>)</span></span> {
        TODO(<span class="hljs-string">"Not yet implemented"</span>)
    }
}
</code></pre>
<h3 id="heading-first-test-scenario"><strong>First test scenario</strong></h3>
<p>With that out of the way, we can get back to writing our test. Let's create an instance of a <code>NewActivityViewModel</code> using our fakes:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel exposes loading ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )
}
</code></pre>
<p>Now we want to test that after creating the <code>viewModel</code> the initial value of the <code>uiState</code> is <code>NewActivityUiState.Loading</code>.</p>
<p>Here are a couple of things to keep in mind when writing this first test.</p>
<p>First, <code>StateFlow</code> always has a <code>value</code> or a state (hence the name), so we can access it synchronously with <code>viewModel.uiState.value</code>. We don't need to be inside a coroutine to do that.</p>
<p>Second, people use many different libraries in their tests for assertions, but we will use the standard assertion functions that come with Kotlin and JUnit to make things easier.</p>
<p>With that in mind we can finish our test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel exposes loading ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    <span class="hljs-comment">// Assert</span>
    assert(viewModel.uiState.value <span class="hljs-keyword">is</span> NewActivityUiState.Loading)
}
</code></pre>
<p>Now, if we run this test, we will get an error:</p>
<pre><code class="lang-kotlin">Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"Test worker"</span> java.lang.IllegalStateException: 
Module with the Main dispatcher had failed to initialize. 
For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used
</code></pre>
<p>This happens because creating a new instance of <code>NewActivityViewModel</code> immediately calls <code>loadNewActivity()</code> method, which launches a new coroutine in the <code>viewModelScope</code>.</p>
<p>This scope uses the <code>Dispatchers.Main.immediate</code> dispatcher, and since <code>Dispatcher.Main</code> usually comes with the framework responsible for drawing UI and otherwise is not readily available, we will have to supply our own dispatcher.</p>
<p>Luckily, this is very easy to do, and the error message even gives us a hint. We can use <code>Dispatchers.setMain()</code> method from <code>kotlinx-coroutines-test</code> module.</p>
<p>Let's add it to our project:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
coroutines_test_version = <span class="hljs-string">'1.6.1'</span>

<span class="hljs-comment">// module build.gradle</span>
testImplementation <span class="hljs-string">"org.jetbrains.kotlinx:kotlinx-coroutines-test:<span class="hljs-variable">$coroutines_test_version</span>"</span>
</code></pre>
<p>Now we can set the <code>StandartTestDispatcher</code>, which comes from the <code>kotlinx-coroutines-test</code> library, as our <code>Dispatchers.Main</code>. It is a good practice to set and reset the <code>Dispatchers.Main</code> before and after each test, and for that, we can use <code>@Before</code> and <code>@After</code> annotations that come with <code>JUnit</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewActivityViewModelTest</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> testDispatcher = StandardTestDispatcher()

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span></span> {
        Dispatchers.setMain(testDispatcher)
    }

    <span class="hljs-meta">@After</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">tearDown</span><span class="hljs-params">()</span></span> {
        Dispatchers.resetMain()
    }

    ...
}
</code></pre>
<blockquote>
<p>Note: We also need to add either <code>@ExperimentalCoroutinesApi</code> or <code>@OptIn(ExperimentalCoroutinesApi::class)</code> to the class since most of the stuff inside <code>kotlinx-coroutines-test</code> is experimental.</p>
</blockquote>
<p>Since we can set the <code>Dispatchers.Main</code> ourselves in the tests, we can easily test coroutine scopes that use this dispatcher (like <code>viewModelScope</code> or <code>lifecycleScope</code>) without injecting a test scope. However, we must replace the scopes that use other dispatchers with a <code>TestScope</code>. We will look into those scenarios a bit later.</p>
<p>If we run our test now, it finally passes, and we have our first working test!</p>
<h3 id="heading-creating-test-rules"><strong>Creating test rules</strong></h3>
<p>It took us a while to get our first test running, but we are still in the process of setting up, so test writing will speed up as we go.</p>
<p>One of the things that we can do to speed it up even more, is to create a <code>Rule</code> that will be responsible for setting and resetting the <code>Dispatchers.Main</code>. This way, we can re-use this logic in other test files.</p>
<p>Let's create a new package <code>eu.maxkim.boredombuster.util</code> with a new class <code>CoroutineRule</code>.</p>
<p>To get the <code>@Before</code> and <code>@After</code> behavior, we can extend an abstract <code>TestWatcher</code> class, which comes with <code>starting</code> and <code>finished</code> methods.</p>
<p>After overriding these methods we get:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoroutineRule</span></span>(
    <span class="hljs-keyword">val</span> testDispatcher: TestDispatcher = StandardTestDispatcher()
) : TestWatcher() {

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">starting</span><span class="hljs-params">(description: <span class="hljs-type">Description</span>?)</span></span> {
        Dispatchers.setMain(testDispatcher)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">finished</span><span class="hljs-params">(description: <span class="hljs-type">Description</span>?)</span></span> {
        Dispatchers.resetMain()
    }
}
</code></pre>
<p>With our <code>CoroutineRule</code> ready, let's go back to our test and replace the <code>@Before</code> and <code>@After</code> logic with the rule. For that, we need to add the following to our test class:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@get:Rule</span>
<span class="hljs-keyword">val</span> coroutineRule = CoroutineRule()
</code></pre>
<blockquote>
<p><code>@get:Rule</code> annotation comes from <code>JUnit</code>.</p>
</blockquote>
<p>With that in place, here is what our test file looks like now:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewActivityViewModelTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> coroutineRule = CoroutineRule()

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel exposes loading ui state`<span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
            FakeGetRandomActivity(),
            FakeSaveActivity(),
            FakeDeleteActivity(),
            FakeIsActivitySaved()
        )

        <span class="hljs-comment">// Assert</span>
        assert(viewModel.uiState.value <span class="hljs-keyword">is</span> NewActivityUiState.Loading)
    }
}
</code></pre>
<p>Run the test to make sure that everything works as before.</p>
<h3 id="heading-understanding-test-dispatchers-after-kotlin-coroutines-16"><strong>Understanding test dispatchers after Kotlin Coroutines 1.6</strong></h3>
<p>Before we move on to our second test scenario, I would like to talk about why this test works. One might assume that this test should be flaky since creating the <code>NewActivityViewModel</code> loads a new activity immediately and changes the UI state to <code>NewActivityUiState.Success</code>.</p>
<p>However, we confidently check the UI state and expect it always to be <code>NewActivityUiState.Loading</code>. </p>
<p>The secret here is the <code>StandardTestDispatcher()</code>. Coroutines launched on this dispatcher are not executed immediately, which is a big difference compared to how testing coroutines worked before <code>kotlinx.coroutines 1.6.0</code>.</p>
<p>Here is an excerpt from <code>StandardTestDispatcher()</code> documentation:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * In practice, this means that [launch] or [async] blocks 
 * will not be entered immediately (unless they are
 * parameterized with [CoroutineStart.UNDISPATCHED]), 
 * and one should either call [TestCoroutineScheduler.runCurrent] to
 * run these pending tasks, which will block until there are 
 * no more tasks scheduled at this point in time, or, when
 * inside [runTest], call [yield] to yield the (only) thread 
 * used by [runTest] to the newly-launched coroutines.
 */</span>
</code></pre>
<p>This means that the coroutine that we launch inside the <code>loadNewActivity()</code> method is not executed unless we explicitly specify it, which we will do for our next test scenario.</p>
<p>If we need our tests to run blocking as they did in the old testing API, which might be useful during a migration to the new API, we can replace the <code>StandardTestDispatcher()</code> with the <code>UnconfinedTestDispatcher()</code>. Using this dispatcher gives us a much closer behavior to <code>runBlockingTest</code> from the old testing API, since it executes all launched coroutines eagerly.</p>
<p>For learning purposes, you can try replacing the <code>StandardTestDispatcher()</code> in the <code>CoroutineRule</code> with the <code>UnconfinedTestDispatcher()</code>, which will make our test fail. In that case, when we make our assertion, the UI state will already be <code>NewActivityUiState.Success</code>. However, if you do change it, don't forget to change it back!</p>
<h3 id="heading-remaining-test-scenarios">Remaining test scenarios</h3>
<p><strong>Second test scenario</strong></p>
<p>Now that we better understand how testing coroutines work, we can start writing our next test.</p>
<p>We will test that after an instance of <code>NewActivityViewModel</code> is created and all the coroutines have successfully finished, the UI state is <code>NewActivityUiState.Success</code>.</p>
<p>We prepare our <code>viewModel</code> an also an <code>expectedUiState</code> that we should get if everything works correctly:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel updates ui state to success after loading`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    <span class="hljs-keyword">val</span> expectedUiState = NewActivityUiState.Success(activity1, <span class="hljs-literal">false</span>)
}
</code></pre>
<p>Now we need to execute our coroutine that loads a new activity from the <code>FakeGetRandomActivity</code> use case. There are many ways to achieve that, but for now, we will go with the easiest and most straightforward way to do it, which is calling <code>runCurrent()</code> on a <code>TestCoroutineScheduler</code> used by our <code>TestDispatcher</code>. You can also use <code>advanceUntilIdle()</code> to get the same result. There is a difference between these two functions, but we will discuss this difference and how the scheduler and dispatcher are connected a bit later. We can access the <code>TestDispatcher</code> and the <code>TestCoroutineScheduler</code> from our <code>CoroutineRule</code>.</p>
<p>After that, we can do our assertions and expect the test to pass.</p>
<p>Here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel updates ui state to success after loading`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    <span class="hljs-keyword">val</span> expectedUiState = NewActivityUiState.Success(activity1, <span class="hljs-literal">false</span>)

    <span class="hljs-comment">// Act</span>
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    <span class="hljs-keyword">val</span> actualState = viewModel.uiState.value
    assertEquals(actualState, expectedUiState)
}
</code></pre>
<p><strong>Third test scenario</strong></p>
<p>We should also test that the UI state correctly updates to <code>NewActivityUiState.Error</code> if something goes wrong. With all the things we have already discussed, writing this test should be a breeze. All we have to do is to make our fake return an error.</p>
<p>Here is the final result:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `creating a viewmodel updates ui state to error <span class="hljs-keyword">in</span> case of failure`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(isSuccessful = <span class="hljs-literal">false</span>), <span class="hljs-comment">// our fake will return an error</span>
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    <span class="hljs-comment">// Act</span>
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    <span class="hljs-keyword">val</span> currentState = viewModel.uiState.value
    assert(currentState <span class="hljs-keyword">is</span> NewActivityUiState.Error)
}
</code></pre>
<p><strong>Fourth test scenario</strong></p>
<p>In this scenario, we want to test that, if the activity is already saved, the UI state's <code>isFavorite</code> flag is set to <code>true</code>. Given everything we already know, this shouldn't be that hard.</p>
<p>Here is the final test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `<span class="hljs-keyword">if</span> activity <span class="hljs-keyword">is</span> already saved, ui state's isFavorite <span class="hljs-keyword">is</span> <span class="hljs-keyword">set</span> to <span class="hljs-literal">true</span>`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(), <span class="hljs-comment">// our fake will return an error</span>
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved(isActivitySaved = <span class="hljs-literal">true</span>)
    )

    <span class="hljs-keyword">val</span> expectedUiState = NewActivityUiState.Success(activity1, <span class="hljs-literal">true</span>)

    <span class="hljs-comment">// Act</span>
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    <span class="hljs-keyword">val</span> actualState = viewModel.uiState.value
    assertEquals(actualState, expectedUiState)
}
</code></pre>
<p><strong>Fifth test scenario</strong></p>
<p>This scenario is a bit harder since we will be testing whether the new activity loads and replaces the current one when calling <code>loadNewActivity()</code> explicitly.</p>
<p>First of all, let's change our <code>FakeGetRandomActivity</code> to be able to return a new activity when called a second time. The easiest way to do that is to expose a property, which will be returned by the fake if set:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeGetRandomActivity</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> isSuccessful: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">true</span>
) : GetRandomActivity {

    <span class="hljs-keyword">var</span> activity: Activity? = <span class="hljs-literal">null</span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: Result&lt;Activity&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> (isSuccessful) {
            Result.Success(activity ?: activity1)
        } <span class="hljs-keyword">else</span> {
            Result.Error(RuntimeException(<span class="hljs-string">"Boom..."</span>))
        }
    }
}
</code></pre>
<p>We cannot pass the activity in the constructor since we will need to swap it on the same instance.</p>
<p>With that in place, we can now write a test for this scenario:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">loadNewActivity</span><span class="hljs-params">()</span></span> updates ui state with a new activity`() {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> fakeGetRandomActivity = FakeGetRandomActivity()
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        fakeGetRandomActivity,
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )
    <span class="hljs-comment">// this can be omitted, but it is nice to not have any pending tasks</span>
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-keyword">val</span> expectedUiState = NewActivityUiState.Success(activity2, <span class="hljs-literal">false</span>)
    fakeGetRandomActivity.activity = activity2

    <span class="hljs-comment">// Act</span>
    viewModel.loadNewActivity()
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    <span class="hljs-keyword">val</span> actualState = viewModel.uiState.value
    assertEquals(actualState, expectedUiState)
}
</code></pre>
<p>We are not testing the state of our view model after the first call to <code>loadNewActivity()</code> since we already have a dedicated test for that. Therefore, we are only interested in the second call.</p>
<p>Also, in general, Unit tests should be as small as possible, aiming to assert only one scenario. That said, if you want to throw in another assertion and test the UI state before and after, nobody will call the police on you.</p>
<p><strong>Sixth scenario</strong></p>
<p>In this scenario, we will be testing whether or not calling <code>setIsFavorite(activity, true)</code> method interacts with the correct use case, and as I have mentioned before, testing interactions is what <strong><em>mocks</em></strong> are good for.</p>
<p>However, we will have plenty of time to play around with <strong><em>mocks</em></strong> later, so for this <code>ViewModel</code>, let's see how we can test interaction with <strong><em>fakes</em></strong>, so that we have both options.</p>
<p>To do that, we need to introduce a state to our fake, which will change after we invoke it. After that, we will use this state in our assertions.</p>
<p>Here is what our <code>FakeSaveActivity</code> looks like after the changes:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeSaveActivity</span> : <span class="hljs-type">SaveActivity {</span></span>

    <span class="hljs-keyword">var</span> wasCalled = <span class="hljs-literal">false</span>
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">set</span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">(activity: <span class="hljs-type">Activity</span>)</span></span> {
        wasCalled = <span class="hljs-literal">true</span>
    }
}
</code></pre>
<blockquote>
<p>Note: We are using <code>private set</code> to make sure that the only way to change the state is to call the <code>invoke()</code> method</p>
</blockquote>
<p>With that in place, we can write our test as follows:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">setIsFavorite</span><span class="hljs-params">(<span class="hljs-literal">true</span>)</span></span> triggers SaveActivity use case`() {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> fakeSaveActivity = FakeSaveActivity()
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        fakeSaveActivity,
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    <span class="hljs-comment">// Act</span>
    viewModel.setIsFavorite(activity1, <span class="hljs-literal">true</span>)
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    assert(fakeSaveActivity.wasCalled)
}
</code></pre>
<p><strong>Seventh scenario</strong></p>
<p>The test for <code>setIsFavorite(activity, false)</code> is exactly the same, so here is the final result:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">setIsFavorite</span><span class="hljs-params">(<span class="hljs-literal">false</span>)</span></span> triggers DeleteActivity use case`() {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> fakeDeleteActivity = FakeDeleteActivity()
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        FakeGetRandomActivity(),
        FakeSaveActivity(),
        fakeDeleteActivity,
        FakeIsActivitySaved()
    )

    <span class="hljs-comment">// Act</span>
    viewModel.setIsFavorite(activity1, <span class="hljs-literal">false</span>)
    coroutineRule.testDispatcher.scheduler.runCurrent()

    <span class="hljs-comment">// Assert</span>
    assert(fakeDeleteActivity.wasCalled)
}
</code></pre>
<p><strong>Other scenarios</strong></p>
<p>There are still some untested scenarios left in the <code>NewActivityViewModel</code>. For example, testing that calling <code>setIsFavorite()</code> also changes the UI state appropriately. However, these tests are very similar to what we have already discussed and don't provide any educational value to include in this article.</p>
<p>That said, in the <code>finish</code> branch of <a target="_blank" href="https://github.com/mkims/boredom-buster">this project</a>, I will include as many of these tests as possible, so you can reference them if you wish.</p>
<h3 id="heading-bonus-testing-flows-with-turbine">Bonus: Testing Flows with Turbine</h3>
<p>In the above test scenarios, we had the pleasure of dealing with a <code>StateFlow</code>, which allows us to access its <code>value</code> outside a coroutine. Of course, we could have also used <code>first()</code>, but that is a suspend function, and we would have needed a coroutine for that. That said, when testing Android apps, there will be a lot of scenarios where you will need a coroutine (plenty of those examples later on), and maybe you will want to collect multiple values from a <code>Flow</code> for assertion.</p>
<p>Testing <em>hot flows</em> like <code>StateFlow</code> (they never finish) might be tricky in these scenarios.</p>
<p>And that's where <a target="_blank" href="https://github.com/cashapp/turbine">Turbine</a> comes in.</p>
<p>It is a small library that makes testing <code>Flow</code>s really easy and intuitive.</p>
<p>To illustrate how it works, let's use Turbine to rewrite the test where we call <code>loadNewActivity()</code> the second time.</p>
<blockquote>
<p>Since this is a bonus section, I will not discuss most of the used concepts and will focus on the Turbine library. However, we will cover everything else later in the article, so feel free to return to this section later if something doesn't make sense.</p>
</blockquote>
<p>First, we have to add it to the dependencies:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
turbine_version = <span class="hljs-string">'0.8.0'</span>

<span class="hljs-comment">// module build.gradle</span>
testImplementation <span class="hljs-string">"app.cash.turbine:turbine:<span class="hljs-variable">$turbine_version</span>"</span>
</code></pre>
<p>Now we can test our <code>Flow</code>s in the following manner:</p>
<pre><code class="lang-kotlin">flowOf(<span class="hljs-string">"one"</span>, <span class="hljs-string">"two"</span>).test {
    assertEquals(<span class="hljs-string">"one"</span>, awaitItem())
    assertEquals(<span class="hljs-string">"two"</span>, awaitItem())
    awaitComplete()
}
</code></pre>
<p>With that in mind, let's test the following scenario again.</p>
<ul>
<li>We want the initial state of UI to be <code>Loading</code>;</li>
<li>Then, after the first load completes, we expect the state to change to <code>Success</code> with the corresponding activity;</li>
<li>Calling <code>loadNewActivity()</code> again should change the state back to <code>Loading</code> and finish with another <code>Success</code> containing the second activity.</li>
</ul>
<p>The Turbine's <code>test()</code> function is a suspend function, so we will need to run our test with the <code>runTest</code> coroutine builder (again, if you don't know what it is, please return to this bonus section later).</p>
<p>Also, we will have to collect our flow with the <code>test()</code> function in a separate coroutine so it is not suspending the whole test.</p>
<p>With those details out of the way, here is how we can test this scenario with Turbine:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">loadNewActivity</span><span class="hljs-params">()</span></span> twice goes through expected ui states`() = runTest {
    <span class="hljs-keyword">val</span> fakeGetRandomActivity = FakeGetRandomActivity()
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        fakeGetRandomActivity,
        FakeSaveActivity(),
        FakeDeleteActivity(),
        FakeIsActivitySaved()
    )

    assert(viewModel.uiState.value <span class="hljs-keyword">is</span> NewActivityUiState.Loading)

    launch {
        viewModel.uiState.test {
            with(awaitItem()) {
                assert(<span class="hljs-keyword">this</span> <span class="hljs-keyword">is</span> NewActivityUiState.Success)
                assertEquals((<span class="hljs-keyword">this</span> <span class="hljs-keyword">as</span> NewActivityUiState.Success).activity, activity1)
            }

            assert(awaitItem() <span class="hljs-keyword">is</span> NewActivityUiState.Loading)

            with(awaitItem()) {
                assert(<span class="hljs-keyword">this</span> <span class="hljs-keyword">is</span> NewActivityUiState.Success)
                assertEquals((<span class="hljs-keyword">this</span> <span class="hljs-keyword">as</span> NewActivityUiState.Success).activity, activity2)
            }
            <span class="hljs-comment">// this is not necessary for this specific test</span>
            <span class="hljs-comment">// but better safe than sorry</span>
            <span class="hljs-comment">// especially when dealing with hot flows</span>
            cancelAndIgnoreRemainingEvents()
        }
    }

    <span class="hljs-comment">// runs the initial loading</span>
    runCurrent()

    <span class="hljs-comment">// prepares and runs the second loading</span>
    fakeGetRandomActivity.activity = activity2
    viewModel.loadNewActivity()
    runCurrent()
}
</code></pre>
<p>This is just a brief introduction to Turbine. It has much more to offer when testing different scenarios with <code>Flow</code>s. So keep it in mind if you need to write more complex tests.</p>
<p>With that out of the way, let's get back to testing our app!</p>
<h2 id="heading-testing-viewmodels-with-livedata">Testing ViewModels with LiveData</h2>
<p>Now let's take a look at how we can test <code>LiveData</code>.</p>
<p>In the app, we have a second <code>ViewModel</code>, which is a good candidate for that - the <code>FavoritesViewModel</code>.</p>
<p>This <code>ViewModel</code> is quite small. There are only three scenarios:</p>
<ol>
<li>The view model exposes the list of activities from <code>LiveData</code> as a List UI state;</li>
<li>The view model exposes an empty list from <code>LiveData</code> as an Empty UI state;</li>
<li>Calling <code>deleteActivity()</code> triggers interaction with the correct use case.</li>
</ol>
<p>Create a test file for the <code>FavoritesViewModel</code>, and let's get started.</p>
<h3 id="heading-first-scenario-and-introduction-to-mockito"><strong>First scenario and introduction to Mockito</strong></h3>
<p>The first thing that we need to consider when testing <code>LiveData</code> is that it also heavily relies on the main UI thread. We already know how to deal with this issue when testing coroutines. We have made a custom <code>CoroutineRule</code> which sets and resets the main thread using the <code>Dispatchers.setMain()</code> and <code>Dispatchers.resetMain()</code> methods.</p>
<p>This time around, we don't have to do anything ourselves since folk at Google kindly provided us with a solution to this problem.</p>
<p>There is a dedicated package for testing Architecture Components, which we can add to our project:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
arch_testing_version = <span class="hljs-string">'2.1.0'</span>

<span class="hljs-comment">// module build.gradle</span>
testImplementation <span class="hljs-string">"androidx.arch.core:core-testing:<span class="hljs-variable">$arch_testing_version</span>"</span>
</code></pre>
<p>The class that we are interested in is <code>InstantTaskExecutorRule</code>, which does exactly what our <code>CoroutineRule</code> does, only for Architecture components.</p>
<pre><code class="lang-java"><span class="hljs-comment">/**
 * A JUnit Test Rule that swaps the background executor 
 * used by the Architecture Components with a
 * different one which executes each task synchronously.
 * &lt;p&gt;
 * You can use this rule for your host side tests that 
 * use Architecture Components.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InstantTaskExecutorRule</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">TestWatcher</span> </span>{
   ...
}
</code></pre>
<p>If you look at its implementation, you will find a very familiar pattern. It also overrides <code>starting</code> and <code>finished</code> methods of <code>TestWatcher</code> to change and reset the executor.</p>
<p>Now let's add this rule to our <code>FavoritesViewModelTest</code>:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FavoritesViewModelTest</span> </span>{

    <span class="hljs-meta">@get</span>:Rule
    val instantExecutorRule = InstantTaskExecutorRule()
}
</code></pre>
<p>One important thing to address is that, unlike <code>StateFlow</code>, <code>LiveData</code> doesn't have a mandatory initial value. Moreover, <code>LiveData</code> is written in Java, and its <code>value</code> doesn't always make sense in Kotlin.</p>
<p>For example, our <code>LiveData</code> type is <code>LiveData&lt;FavoritesUiState&gt;</code>, so one would assume that the <code>value</code> is non-nullable. However, that is not the case.</p>
<p>If we create a new instance of <code>FavoritesViewModel</code> and immediately check <code>viewModel.uiStateLiveData.value</code> it will be <code>null</code>.</p>
<p>So to properly test our <code>LiveData</code>, we have to replicate the observer pattern.</p>
<p>There are a couple of ways to do it. There is a way <a target="_blank" href="https://developer.android.com/codelabs/advanced-android-kotlin-training-testing-basics?hl=vi#8">suggested by Google in their codelabs</a>, but for me, honestly, it looks like a hassle. If you want to go that route, that logic can be simplified and made more elegant. That would be just like using <strong>fakes</strong> with a state. But we already did that, so let's take a different approach and use <strong>mocks</strong> for this one.</p>
<p>The most popular mock library out there is Mockito, and you will probably use it in your tests one way or another, so let's add it to our project:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
mockito_kotlin_version = <span class="hljs-string">'4.0.0'</span>

<span class="hljs-comment">// module build.gradle</span>
testImplementation <span class="hljs-string">"org.mockito.kotlin:mockito-kotlin:<span class="hljs-variable">$mockito_kotlin_version</span>"</span>
</code></pre>
<blockquote>
<p>Note: We are using <code>mockito-kotlin</code> instead of <code>mockito-core</code> to have some cool Kotlin methods.</p>
</blockquote>
<p>Now we can start using Mockito in our tests. To create mocks by using Kotlin's <code>mock()</code>  function (more on that a bit later) or the equivalent Java's <code>Mockito.mock()</code>, we don't need to do anything else.</p>
<p>However, if we want to use Mockito's annotations to initiate mocks, we need to either run the test with <code>MockitoJUnitRunner</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@RunWith(MockitoJUnitRunner::class)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTest</span> </span>{

    <span class="hljs-meta">@Mock</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> mockComponent: Component
}
</code></pre>
<p>or add a Mockito <code>Rule</code> to it:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> mockitoRule: MockitoRule = MockitoJUnit.rule()

    <span class="hljs-meta">@Mock</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> mockComponent: Component
}
</code></pre>
<blockquote>
<p>Note: We specify the explicit type <code>MockitoRule</code> because <code>MockitoJUnit.rule()</code> returns a platform type, and we want to make the compiler happy.</p>
</blockquote>
<p>The <code>FavoritesViewModelTest</code> has two dependencies. We already have a fake for <code>DeleteActivity</code>, and we can easily make a fake for <code>GetFavoriteActivities</code>. But since we are in the Mockito world right now, let's use <strong><em>mocks</em></strong> this time.</p>
<p>Mockito is quite a flexible library, and it gives us options on how we can approach things, but I find that the easiest way to create mocks in our tests is to use the <code>mock()</code> method from <code>mockito-kotlin</code> library:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Creates a mock for [T].
 */</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;<span class="hljs-keyword">reified</span> T : Any&gt;</span> <span class="hljs-title">mock</span><span class="hljs-params">()</span></span>: T
</code></pre>
<p>This is a simplified Kotlin way to call Java's:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">mock</span><span class="hljs-params">(Class&lt;T&gt; classToMock, MockSettings mockSettings)</span></span>
</code></pre>
<p>Now that we know how to create a mock, let's add the mocks for our use cases to the test class:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FavoritesViewModelTest</span> </span>{

    <span class="hljs-meta">@get</span>:Rule
    val instantExecutorRule = InstantTaskExecutorRule()

    <span class="hljs-keyword">private</span> val mockGetFavoriteActivities: GetFavoriteActivities = mock()
    <span class="hljs-keyword">private</span> val mockDeleteActivity: DeleteActivity = mock()
}
</code></pre>
<p>One concern that can arise with mocks is whether or not we should reset our mocks after each test to avoid a dirty state. The answer is - folk at <code>JUnit</code> made sure that this is not an issue. <code>JUnit</code> will create a new test class instance each time it runs a test. You can read about it in this <a target="_blank" href="https://stackoverflow.com/questions/16815940/do-mock-objects-get-reset-for-each-test">StackOverlow thread</a>. It can also be easily tested by setting the state of a mock in one test and trying to access it from another. Spoiler alert: it will not work.</p>
<p>With those worries out of the way, let's write our test and arrange some data. First, we need a <code>LiveData</code> object that our mock will return and a list we expect to observe.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `the view model maps list of activities to list ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> liveDataToReturn = MutableLiveData&lt;List&lt;Activity&gt;&gt;()
        .apply { value = listOf(activity1, activity2) }

    <span class="hljs-keyword">val</span> expectedList = listOf(activity1, activity2)
}
</code></pre>
<blockquote>
<p>Note: We should not feed <code>expectedList</code> directly into our <code>LiveData</code> because expected and actual values will be the same reference, which can muddy the test result in some cases.</p>
</blockquote>
<p>To set up our mock, we will use Mockito's:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">whenever</span><span class="hljs-params">(methodCall: <span class="hljs-type">T</span>)</span></span>: OngoingStubbing&lt;T&gt;
</code></pre>
<p>together with</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">infix</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> OngoingStubbing<span class="hljs-type">&lt;T&gt;</span>.<span class="hljs-title">doReturn</span><span class="hljs-params">(t: <span class="hljs-type">T</span>)</span></span>: OngoingStubbing&lt;T&gt;
</code></pre>
<p>Kotlin's <code>doReturn()</code> method just calls Java's <code>thenReturn()</code> method. Therefore, we can use those two interchangeably.</p>
<p>Here is how it looks in our code:</p>
<pre><code class="lang-kotlin">whenever(mockGetFavoriteActivities.invoke()).doReturn(liveDataToReturn)
</code></pre>
<blockquote>
<p>Note: We have to set up our mock before creating a <code>ViewModel</code> instance. Otherwise, <code>ViewModel</code>'s <code>MediatorLiveData</code> that does the mapping won't have any sources and will crash with a <code>NullPointerException</code>.</p>
</blockquote>
<p>With everything set up, we can now create an instance of our <code>ViewModel</code> and the arranging part is done:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `the view model maps list of activities to list ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> liveDataToReturn = MutableLiveData&lt;List&lt;Activity&gt;&gt;()
        .apply { value = listOf(activity1, activity2) }

    <span class="hljs-keyword">val</span> expectedList = listOf(activity1, activity2)

    whenever(mockGetFavoriteActivities.invoke()).doReturn(liveDataToReturn)

    <span class="hljs-keyword">val</span> viewModel = FavoritesViewModel(
        mockGetFavoriteActivities,
        mockDeleteActivity
    )
}
</code></pre>
<p>Now we need an <code>Observer</code> to observe our <code>LiveData</code> and something that can capture the observed data and preserve it in a state for us to use in our assertions. This is similar to how Google approaches this problem in the Codelab mentioned above, but we can use an <code>ArgumentCaptor&lt;T&gt;</code> from Mockito to do this for us.</p>
<pre><code class="lang-java"><span class="hljs-comment">/**
 * Use it to capture argument values for further assertions.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArgumentCaptor</span>&lt;<span class="hljs-title">T</span>&gt;</span>
</code></pre>
<p>We can create an <code>Observer</code> mock just like we did with the use cases:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> activityListObserver: Observer&lt;FavoritesUiState&gt; = mock()
</code></pre>
<p>However, for an <code>ArgumentCaptor</code>, we need a real instance. There are two ways to do it (as far as I know). The first one is mentioned in the documentation and uses a static builder method:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;U, S extends U&gt; <span class="hljs-function">ArgumentCaptor&lt;U&gt; <span class="hljs-title">forClass</span><span class="hljs-params">(Class&lt;S&gt; clazz)</span></span>
</code></pre>
<p>Here we need to pass a <code>Class&lt;S&gt;</code> as an argument, and in our case, we would write:</p>
<pre><code class="lang-java">ArgumentCaptor.forClass(FavoritesUiState::class.java)
</code></pre>
<p>However, the second option is easier and more elegant for my taste.</p>
<p>We can use the <code>@Captor</code> annotation to generate the captor for us:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Captor</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> activityListCaptor: ArgumentCaptor&lt;FavoritesUiState&gt;
</code></pre>
<p>Now, since we will be using a Mockito annotation to create this mock, we will need to either run our test with the <code>MockitoJUnitRunner</code> or add a <code>MockitoRule</code> as explained above.</p>
<p>I will go with the <code>MockitoJUnitRunner</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@RunWith(MockitoJUnitRunner::class)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FavoritesViewModelTest</span> </span>{

    ...
}
</code></pre>
<p>And here are the new mocks in our file:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> activityListObserver: Observer&lt;FavoritesUiState&gt; = mock()

<span class="hljs-meta">@Captor</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> activityListCaptor: ArgumentCaptor&lt;FavoritesUiState&gt;
</code></pre>
<p>With that settled, we can now finish our test.</p>
<p>We need to start observing the <code>LiveData</code> with our mock <code>Observer</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Act</span>
viewModel.favoriteActivityLiveData.observeForever(activityListObserver)
</code></pre>
<blockquote>
<p>Note: We are using <code>observeForever</code> since we don't have a <code>LifecycleOwner</code>.</p>
</blockquote>
<p>Assertion part might seem a bit scary at first, but it is really straightforward if you break it down:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Assert</span>
verify(activityListObserver, times(<span class="hljs-number">1</span>)).onChanged(activityListCaptor.capture())
assert(activityListCaptor.value <span class="hljs-keyword">is</span> FavoritesUiState.List)

<span class="hljs-keyword">val</span> actualList = (activityListCaptor.value <span class="hljs-keyword">as</span> FavoritesUiState.List).activityList
assertEquals(actualList, expectedList)
</code></pre>
<p>We are verifying that our mock <code>Observer</code>’s <code>onChanged</code> method is called once, and we are using the <code>activityListCaptor</code> to capture the passed value.</p>
<p>After that, we can access the <code>activityListCaptor.value</code>, which is a <code>FavoritesUiState</code>, and compare its <code>activityList</code> to <code>expectedList</code>.</p>
<p>Here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `the view model maps list of activities to list ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> liveDataToReturn = MutableLiveData&lt;List&lt;Activity&gt;&gt;()
        .apply { value = listOf(activity1, activity2) }

    <span class="hljs-keyword">val</span> expectedList = listOf(activity1, activity2)

    whenever(mockGetFavoriteActivities.invoke()).doReturn(liveDataToReturn)

    <span class="hljs-keyword">val</span> viewModel = FavoritesViewModel(
        mockGetFavoriteActivities,
        mockDeleteActivity
    )

    <span class="hljs-comment">// Act</span>
    viewModel.favoriteActivityLiveData.observeForever(activityListObserver)

    <span class="hljs-comment">// Assert</span>
    verify(activityListObserver, times(<span class="hljs-number">1</span>)).onChanged(activityListCaptor.capture())
    assert(activityListCaptor.value <span class="hljs-keyword">is</span> FavoritesUiState.List)

    <span class="hljs-keyword">val</span> actualList = (activityListCaptor.value <span class="hljs-keyword">as</span> FavoritesUiState.List).activityList
    assertEquals(actualList, expectedList)
}
</code></pre>
<h3 id="heading-second-test-scenario"><strong>Second test scenario</strong></h3>
<p>The second scenario is very similar to the first one, but we will be returning an empty list from our mock's <code>LiveData</code> and asserting that the <code>FavoritesUiState</code> is <code>Empty</code>.</p>
<p>There is nothing new here, so here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `the view model maps empty list of activities to empty ui state`<span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> liveDataToReturn = MutableLiveData&lt;List&lt;Activity&gt;&gt;()
        .apply { value = listOf() }

    whenever(mockGetFavoriteActivities.invoke()).doReturn(liveDataToReturn)

    <span class="hljs-keyword">val</span> viewModel = FavoritesViewModel(
        mockGetFavoriteActivities,
        mockDeleteActivity
    )

    <span class="hljs-comment">// Act</span>
    viewModel.uiStateLiveData.observeForever(activityListObserver)

    <span class="hljs-comment">// Assert</span>
    verify(activityListObserver, times(<span class="hljs-number">1</span>)).onChanged(activityListCaptor.capture())
    assert(activityListCaptor.value <span class="hljs-keyword">is</span> FavoritesUiState.Empty)
}
</code></pre>
<h3 id="heading-third-test-scenario"><strong>Third test scenario</strong></h3>
<p>In this scenario, we will be testing whether calling <code>deleteActivity()</code> interacts with the correct use case. We have already done a similar test, so let's do this one using <strong><em>mocks</em></strong> to have both options.</p>
<p>The <code>Arrange</code> and <code>Act</code> parts in this test are quite straight forward:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">deleteActivity</span><span class="hljs-params">()</span></span> interacts with the correct use case`() {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = FavoritesViewModel(
        mockGetFavoriteActivities,
        mockDeleteActivity
    )

    <span class="hljs-comment">// Act</span>
    viewModel.deleteActivity(activity1)
}
</code></pre>
<p>The first problem, however, is that <code>deleteActivity()</code> launches a coroutine in the <code>viewModelScope</code>, and we need to set the <code>Dispatcher.Main</code>. But we already know how to fix that.</p>
<p>Let's add our <code>CoroutineRule</code> to this test class:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@get:Rule</span>
<span class="hljs-keyword">val</span> coroutineRule = CoroutineRule()
</code></pre>
<p>The second problem presents itself if we try to verify that the <code>deleteActivity()</code> method interacted with our <code>mockDeleteActivity</code>. We have seen how to check for the interactions in the previous test, so we would write:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Assert</span>
verify(mockDeleteActivity, times(<span class="hljs-number">1</span>)).invoke(activity1)
</code></pre>
<p>The problem here is that our use case's <code>invoke()</code> method is <code>suspend</code>, so we need a coroutine.</p>
<p>We have managed to avoid using <code>suspend</code> functions until now, but those are pretty common in Android applications.</p>
<p>Since <code>kotlinx.coroutines 1.6.0</code> the way to get into the coroutine world in tests is by using <code>runTest</code> coroutine builder. It replaced the <code>runBlockingTest</code>, which is now deprecated.</p>
<p>By wrapping our test with <code>runTest</code> we won't have any more compilation errors, but don't forget to add <code>runCurrent()</code> or <code>advanceUntilIdle()</code> after calling <code>deleteActivity()</code> to make sure the launched coroutine completes its job.</p>
<blockquote>
<p>Note: We can also use the <code>yield()</code> suspend function when inside a <code>runTest</code> block to get the same result. But its name is not as explicit as <code>runCurrent()</code> or <code>advanceUntilIdle()</code> and it requires a good understanding of how coroutines work to use comfortably. Therefore, we will not use it in the examples.</p>
</blockquote>
<p>Here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">deleteActivity</span><span class="hljs-params">()</span></span> interacts with the correct use case`() = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = FavoritesViewModel(
        mockGetFavoriteActivities,
        mockDeleteActivity
    )

    <span class="hljs-comment">// Act</span>
    viewModel.deleteActivity(activity1)
    advanceUntilIdle() <span class="hljs-comment">// works the same as runCurrent() in this case</span>

    <span class="hljs-comment">// Assert</span>
    verify(mockDeleteActivity, times(<span class="hljs-number">1</span>)).invoke(activity1)
}
</code></pre>
<h2 id="heading-testing-room-database">Testing Room database</h2>
<p>With <code>ViewModel</code> testing out of the way, the next important area of an app to test is repositories. In our app, the <code>ActivityRepository</code> just delegates data operations to its data sources, so it would make sense to test those.</p>
<p>That said, let's first test the <code>ActivityLocalDataSource</code> and the Room database.</p>
<p>The recommended way to test Room is on an Android device since we need a <code>Context</code> to create a database. Therefore, we will be creating our new test class in the <code>androidTest</code> folder instead of the <code>test</code> one as we did with previous tests.</p>
<p>Let's open up <code>ActivityLocalDataSourceImpl</code> and create a test file for it in the <code>androidTest</code> folder. </p>
<p>First things first, we will be testing the Room database, which is <code>AppDatabase</code> in this app, as well as the <code>ActivityDao</code>. And we will want to create a new database for each test and <code>close()</code> it after we have done testing it. We can use methods annotated with the <code>@Before</code> and <code>@After</code> for that:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActivityLocalDataSourceImplTest</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> activityDao: ActivityDao
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> database: AppDatabase

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDb</span><span class="hljs-params">()</span></span> {
    }

    <span class="hljs-meta">@After</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">closeDb</span><span class="hljs-params">()</span></span> {
    }
}
</code></pre>
<p>We won't be reusing this logic outside this test class, so there is no need to create a separate <code>Rule</code>.</p>
<p>To create an instance of a Room database, we will need an application <code>Context</code>.</p>
<p>We can get one using:</p>
<pre><code class="lang-kotlin">InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
</code></pre>
<p>One thing to mention is that <code>InstrumentationRegistry</code> has this written in its documentation:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * It is generally not recommended for direct use by most tests.
 */</span>
</code></pre>
<p>However, it is used in the auto-generated test that Android Studio kindly provides when creating a new project. Those are very conflicting messages from Google if you ask me.</p>
<p>Anyways, there is also another way to do it:</p>
<pre><code class="lang-kotlin">ApplicationProvider.getApplicationContext&lt;Context&gt;()
</code></pre>
<p>Which uses <code>InstrumentationRegistry</code> under the hood, so its essentially the same thing:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;T extends Context&gt; <span class="hljs-function">T <span class="hljs-title">getApplicationContext</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> (T) InstrumentationRegistry.getInstrumentation()
        .getTargetContext()
        .getApplicationContext();
}
</code></pre>
<p>You can use whichever approach you want.</p>
<p>Now we can use this <code>Context</code> to create an instance of a Room database. That said, we don't want to create a real database every time we run a test - that would be a bit of an overkill. Luckily, Room provides us with <code>inMemoryDatabaseBuilder</code> API, which builds an in-memory version of the database.</p>
<p>This is all we need to set up our <code>createDb()</code> method:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Before</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDb</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> context = ApplicationProvider.getApplicationContext&lt;Context&gt;()
    database = Room.inMemoryDatabaseBuilder(context, AppDatabase::<span class="hljs-keyword">class</span>.java)
        .build()
    activityDao = database.activityDao()
}
</code></pre>
<p>And we should <code>close()</code> it after testing:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@After</span>
<span class="hljs-meta">@Throws(IOException::class)</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">closeDb</span><span class="hljs-params">()</span></span> {
    database.close()
}
</code></pre>
<p>With our test database all set up, we can start writing our tests.</p>
<h3 id="heading-test-scenarios"><strong>Test scenarios</strong></h3>
<p>There are three scenarios we would like to test here:</p>
<ol>
<li>We can save an activity to the database;</li>
<li>We can delete an activity from the database;</li>
<li>We can observe the activity list <code>LiveData</code>.</li>
</ol>
<h3 id="heading-first-test-scenario"><strong>First test scenario</strong></h3>
<p>Let's create a first test that checks if we can save an activity to the database and access it.</p>
<p>We will need to use <code>runTest</code> since we will be using <code>suspend</code> functions, but we don't need our <code>CoroutineRule</code> since we are not in the UI layer anymore and won't be using <code>Dispatchers.Main</code>. The <code>TestScope</code> provided by <code>runTest</code> will be enough. We also don't need to call <code>runCurrent()</code> or <code>advanceUntilIdle()</code> since we are not launching any new coroutines, and the <code>TestScope</code> will wait for its direct children to complete.</p>
<p>Also, keep in mind that <em>files and dependencies are not shared</em> between <code>test</code> and <code>androidTest</code>. Therefore, we cannot use the test models we have set up before. </p>
<p>For the sake of not bloating this article even more (can it even be considered an article at this point?) let's just create a new file inside <code>androidTest</code> with our test models:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// TestAndroidModels.kt</span>
<span class="hljs-keyword">val</span> androidActivity1 = Activity(
    name = <span class="hljs-string">"Learn to dance"</span>,
    type = Activity.Type.Recreational,
    participantCount = <span class="hljs-number">2</span>,
    price = <span class="hljs-number">0.1f</span>,
    accessibility = <span class="hljs-number">0.2f</span>,
    key = <span class="hljs-string">"112233"</span>,
    link = <span class="hljs-string">"www.dance.com"</span>
)

<span class="hljs-keyword">val</span> androidActivity2 = Activity(
    name = <span class="hljs-string">"Pet a dog"</span>,
    type = Activity.Type.Relaxation,
    participantCount = <span class="hljs-number">1</span>,
    price = <span class="hljs-number">0.0f</span>,
    accessibility = <span class="hljs-number">0.1f</span>,
    key = <span class="hljs-string">"223344"</span>,
    link = <span class="hljs-string">"www.dog.com"</span>
)
</code></pre>
<blockquote>
<p>If you want to reuse the files, which is a good idea, you can take a look at <a target="_blank" href="https://stackoverflow.com/questions/39519347/share-test-classes-between-test-and-androidtest">this StackOverflow question</a>.</p>
</blockquote>
<p>Also, as we have discussed previously, we will use regular method naming for <code>androidTest</code> tests.</p>
<p>And here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">canSaveActivityToTheDbAndReadIt</span><span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> activityLocalDataSource = ActivityLocalDataSourceImpl(activityDao)

    <span class="hljs-comment">// Act</span>
    activityLocalDataSource.saveActivity(androidActivity1)

    <span class="hljs-comment">// Assert</span>
    assert(activityLocalDataSource.isActivitySaved(androidActivity1.key))
}
</code></pre>
<blockquote>
<p>Note: I did say that <code>test</code> and <code>androidTest</code> modules do not share dependencies, but somehow <code>androidTest</code> knows about <code>org.jetbrains.kotlinx:kotlinx-coroutines-test</code>. It comes from <code>androidx.compose.ui:ui-test-junit4</code>, which is automatically added when creating a new Compose project in Android Studio.</p>
</blockquote>
<h3 id="heading-second-test-scenario"><strong>Second test scenario</strong></h3>
<p>The second scenario is about deleting an activity from the database.</p>
<p>It is a very similar test to the previous one, so let's just get it out of the way:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">canDeleteActivityFromTheDb</span><span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> activityLocalDataSource = ActivityLocalDataSourceImpl(activityDao)
    activityLocalDataSource.saveActivity(androidActivity1)

    <span class="hljs-comment">// Act</span>
    activityLocalDataSource.deleteActivity(androidActivity1)

    <span class="hljs-comment">// Assert</span>
    assert(!activityLocalDataSource.isActivitySaved(androidActivity1.key))
}
</code></pre>
<blockquote>
<p>Note: <code>saveActivity()</code> is a part of <code>Arrange</code> now. We have a separate test to test that functionality.</p>
</blockquote>
<h3 id="heading-third-test-scenario"><strong>Third test scenario</strong></h3>
<p>This scenario is more complicated, but it should be a breeze given everything we have learned so far.</p>
<p>We will be testing the <code>LiveData</code> coming straight from the database.</p>
<p>We already know what we need to set up to test <code>LiveData</code>, but first, we need to make sure that we have all required dependencies in <code>androidTest</code> module.</p>
<p>We will be using <code>InstantTaskExecutorRule</code>, so let's add:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// module build.gradle</span>
androidTestImplementation <span class="hljs-string">"androidx.arch.core:core-testing:<span class="hljs-variable">$arch_testing_version</span>"</span>
</code></pre>
<p>We will also need Mockito. However, the regular <code>mockito-kotlin</code> library we used before cannot mock objects when running on an Android VM. So we need a different library to use Mockito in our Android instrumented tests - <code>mockito-android</code>.</p>
<p>Let's add it to our dependencies:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
mockito_android_version = <span class="hljs-string">'4.3.1'</span>

<span class="hljs-comment">// module build.gradle</span>
androidTestImplementation <span class="hljs-string">"org.mockito:mockito-android:<span class="hljs-variable">$mockito_android_version</span>"</span>
</code></pre>
<p>And just to be able to use Kotlin Mockito functions, let's add <code>mockito-kotlin</code> as well:</p>
<pre><code class="lang-kotlin">androidTestImplementation <span class="hljs-string">"org.mockito.kotlin:mockito-kotlin:<span class="hljs-variable">$mockito_kotlin_version</span>"</span>
</code></pre>
<p>Now, with all the dependencies sorted out, we can set up our test file, just as we did in the <code>FavoritesViewModel</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-meta">@RunWith(MockitoJUnitRunner::class)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActivityLocalDataSourceImplTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> instantExecutorRule = InstantTaskExecutorRule()

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> activityListObserver: Observer&lt;List&lt;Activity&gt;&gt; = mock()

    <span class="hljs-meta">@Captor</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> activityListCaptor: ArgumentCaptor&lt;List&lt;Activity&gt;&gt;

    ...
}
</code></pre>
<p>And we can now test our <code>LiveData</code> scenario:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">canSaveActivityToTheDbAndObserveTheLiveData</span><span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> activityLocalDataSource = ActivityLocalDataSourceImpl(activityDao)
    <span class="hljs-keyword">val</span> expectedList = listOf(androidActivity1, androidActivity2)

    <span class="hljs-comment">// Act</span>
    activityLocalDataSource.getActivityListLiveData()
        .observeForever(activityListObserver)
    activityLocalDataSource.saveActivity(androidActivity1)
    activityLocalDataSource.saveActivity(androidActivity2)

    <span class="hljs-comment">// Assert</span>
    verify(activityListObserver, times(<span class="hljs-number">3</span>)).onChanged(activityListCaptor.capture())
    assertEquals(activityListCaptor.value, expectedList)
}
</code></pre>
<p>In this test, we start observing the database when there are no entries. Therefore, our first <code>onChanged</code> event will fire with an empty list. We expect our <code>LiveData</code> to be updated after every save, hence <code>onChanged</code> should be triggered three times. And the final list should contain both activities.</p>
<h2 id="heading-testing-retrofit-with-mockwebserver">Testing Retrofit with MockWebServer</h2>
<p>With the local data source out of the way, it is now time to test our <code>ActivityRemoteDataSource</code>.</p>
<p>We won't be testing Retrofit itself since we have no business testing 3rd party libraries in our code. We will, however, test that our <code>ActivityRemoteDataSource</code> correctly returns expected results, depending on the server response.</p>
<p>For that, we need a server. And folk at square have exactly what we need - a <a target="_blank" href="https://github.com/square/okhttp/tree/master/mockwebserver">MockWebServer library</a>.</p>
<p>Unlike Room tests, these tests will not depend on the Android framework. Therefore, we will be creating them in the <code>test</code> module.</p>
<p>Let's add a MockWebServer dependency to that:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// project build.gradle</span>
okhttp_version = <span class="hljs-string">'4.9.3'</span>

<span class="hljs-comment">// module build.gradle</span>
testImplementation <span class="hljs-string">"com.squareup.okhttp3:mockwebserver:<span class="hljs-variable">$okhttp_version</span>"</span>
</code></pre>
<blockquote>
<p>Note: MockWebServer is a part of the <code>okhttp3</code> library.</p>
</blockquote>
<p>After that, we can open up <code>ActivityRemoteDataSourceImpl</code> class and create a new test for it in the <code>test</code> module.</p>
<p>Now, let's add some test responses to a new file <code>TestResponses.kt</code> to keep things tidy:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// TestResponses.kt</span>
<span class="hljs-keyword">val</span> successfulResponse = <span class="hljs-string">"""
    {
      "activity": "Go to a music festival with some friends",
      "type": "social",
      "participants": 4,
      "price": 0.4,
      "link": "",
      "key": "6482790",
      "accessibility": 0.2
    }
"""</span>.trimIndent()

<span class="hljs-keyword">val</span> errorResponse = <span class="hljs-string">"I am not a json :o"</span>
</code></pre>
<p>Let's also add a new <code>Activity</code> model to our <code>TestModels.kt</code> file, which corresponds to the successful response:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// TestModels.kt</span>
<span class="hljs-keyword">val</span> responseActivity = Activity(
    name = <span class="hljs-string">"Go to a music festival with some friends"</span>,
    type = Activity.Type.Social,
    participantCount = <span class="hljs-number">4</span>,
    price = <span class="hljs-number">0.4f</span>,
    accessibility = <span class="hljs-number">0.2f</span>,
    key = <span class="hljs-string">"6482790"</span>,
    link = <span class="hljs-string">""</span>
)
</code></pre>
<p>Creating a <code>MockWebServer</code> is very easy. We just call its constructor. But we have to set up a new instance of Retrofit. I assume that you already know how to do that, so we will not dive into that in detail.</p>
<p>Here is our test file after all the preparations:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActivityRemoteDataSourceImplTest</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> mockWebServer: MockWebServer
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> apiClient: ActivityApiClient

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> client = OkHttpClient.Builder().build()

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> moshi: Moshi = Moshi.Builder()
        .add(ActivityTypeAdapter())
        .build()

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createServer</span><span class="hljs-params">()</span></span> {
        mockWebServer = MockWebServer()

        apiClient = Retrofit.Builder()
            .baseUrl(mockWebServer.url(<span class="hljs-string">"/"</span>)) <span class="hljs-comment">// setting a dummy url</span>
            .client(client)
            .addConverterFactory(MoshiConverterFactory.create(moshi).asLenient())
            .build()
            .create(ActivityApiClient::<span class="hljs-keyword">class</span>.java)
    }

    <span class="hljs-meta">@After</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">shutdownServer</span><span class="hljs-params">()</span></span> {
        mockWebServer.shutdown()
    }
}
</code></pre>
<p>We can test responses by creating a <code>MockResponse</code> and programming it in any way we like. </p>
<p>After that, we can <code>enqueue()</code> this response on our <code>mockWebServer</code>.</p>
<p>And that is all we need to start testing our <code>ActivityRemoteDataSource</code>.</p>
<p>We will have two testing scenarios:</p>
<ol>
<li>Successful response returns <code>Result.Success</code> with an activity;</li>
<li>Error response returns <code>Result.Error</code>.</li>
</ol>
<h3 id="heading-first-test-scenario"><strong>First test scenario</strong></h3>
<p>In the first test, we will test that the correct JSON is parsed successfully into an <code>Activity</code>.</p>
<p>We will need to create a <code>MockResponse</code> that will return our prepared json body and enqueue it. Apart from that, the rest of the test should be really familiar at this point:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `correct response <span class="hljs-keyword">is</span> parsed into success result`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> response = MockResponse()
        .setBody(successfulResponse)
        .setResponseCode(<span class="hljs-number">200</span>)

    mockWebServer.enqueue(response)

    <span class="hljs-keyword">val</span> activityRemoteDataSource = ActivityRemoteDataSourceImpl(apiClient)
    <span class="hljs-keyword">val</span> expectedActivity = responseActivity

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">val</span> result = activityRemoteDataSource.getActivity()

    <span class="hljs-comment">// Assert</span>
    assert(result <span class="hljs-keyword">is</span> Result.Success)
    assertEquals((result <span class="hljs-keyword">as</span> Result.Success).<span class="hljs-keyword">data</span>, expectedActivity)
}
</code></pre>
<h3 id="heading-second-test-scenario"><strong>Second test scenario</strong></h3>
<p>To be honest, we can even write two tests in this scenario. One when the response is successful, but JSON is malformed. And the other when the response itself has failed.</p>
<p>These tests will be almost identical to the previous test. The difference is a malformed JSON and 400 response code when we want to simulate a faulty response.</p>
<p>Here are these two tests:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `malformed response returns json error result`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> response = MockResponse()
        .setBody(errorResponse)
        .setResponseCode(<span class="hljs-number">200</span>)

    mockWebServer.enqueue(response)

    <span class="hljs-keyword">val</span> activityRemoteDataSource = ActivityRemoteDataSourceImpl(apiClient)

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">val</span> result = activityRemoteDataSource.getActivity()

    <span class="hljs-comment">// Assert</span>
    assert(result <span class="hljs-keyword">is</span> Result.Error)
    assert((result <span class="hljs-keyword">as</span> Result.Error).error <span class="hljs-keyword">is</span> JsonDataException)
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `error response returns http error result`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> response = MockResponse()
        .setBody(errorResponse)
        .setResponseCode(<span class="hljs-number">400</span>)

    mockWebServer.enqueue(response)

    <span class="hljs-keyword">val</span> activityRemoteDataSource = ActivityRemoteDataSourceImpl(apiClient)

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">val</span> result = activityRemoteDataSource.getActivity()

    <span class="hljs-comment">// Assert</span>
    assert(result <span class="hljs-keyword">is</span> Result.Error)
    assert((result <span class="hljs-keyword">as</span> Result.Error).error <span class="hljs-keyword">is</span> HttpException)
}
</code></pre>
<p>And that is our <code>ActivityRemoteDataSource</code> fully tested. The <code>MockWebServer</code> is a really valuable tool for testing these scenarios, so take advantage of that.</p>
<h2 id="heading-testing-components-with-injected-coroutinescope-and-coroutinedispatcher">Testing components with injected CoroutineScope and CoroutineDispatcher</h2>
<p>Another important testing case that often comes up in Android development is when we have a component that uses either a custom <code>CoroutineScope</code> or switches to a different <code>CoroutineDispatcher</code>.</p>
<p><code>CoroutineScope</code>s in the presentation layer (<code>viewModelScope</code> and <code>lifecycleScope</code>) use <code>Dispatchec.Main</code>, and we can easily set our own main dispatcher with <code>Dispatchers.setMain()</code>. It is enough for testing coroutines that run on those scopes.</p>
<p>However, if we use, for example, an application-scoped <code>CoroutineScope</code> that runs on <code>Dispatchers.Default</code>, we cannot just replace <code>Dispatchers.Default</code> with our own <code>TestDispatcher</code>.</p>
<p>The same applies to switching to a different <code>CoroutineDispatcher</code> with the <code>withContext()</code> function. For example, if we want to do some network calls on <code>Dispatchers.IO</code> or heavy calculations on <code>Dispatchers.Default</code>.</p>
<blockquote>
<p>Note: Libraries like Retrofit and Room switch to a correct dispatcher under the hood, so there is no need to explicitly switch dispatchers for those libraries. Moreover, it can slow down the execution of your requests and queries. However, in the sample project's <code>ActivityRepositoryImpl</code>, I do switch a dispatcher so we can have this test scenario.</p>
</blockquote>
<p>Now, before we continue, I want to emphasize that, like any other dependency, <em>you should never hardcode</em> your <code>CoroutineScope</code>s and <code>CoroutineDispatcher</code>s. The exception can be made for scopes using <code>Dispathers.Main</code> or switching to <code>Dispatchers.Main</code> since it will not hinder testing for the reasons discussed above. Still, even then it is better to keep the code clean and use dependency injection.</p>
<p>With that out of the way, let's open the <code>ActivityRepositoryImpl</code> class. I have altered this repository a bit so it has both <code>CoroutineScope</code> and <code>CoroutineDispatcher</code> as dependencies, and we can see how we can test it.</p>
<p>When testing scenarios with multiple scopes and dispatchers, the most important thing to keep in mind is that during a test all those scopes and dispatchers <em>must share the same instance of a</em> <code>TestCoroutineScheduler</code>.</p>
<p>Here is a quick overview of the dependencies between <code>TestScope</code>, <code>TestDispatcher</code> and <code>TestCoroutineScheduler</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> testScheduler: TestCoroutineScheduler = TestCoroutineScheduler()
<span class="hljs-keyword">val</span> testDispatcher: TestDispatcher = StandardTestDispatcher(testScheduler)
<span class="hljs-keyword">val</span> testScope: TestScope = TestScope(testDispatcher)
</code></pre>
<p>While passing arguments to any of these constructors is optional, the main takeaway here is that you can pass a <code>TestCoroutineScheduler</code> to a <code>TestDispatcher</code>, and you can pass a <code>TestDispatcher</code> to a <code>TestScope</code>.</p>
<p>That said, given the flexibility of the coroutines API, there are many different ways to make all of our test coroutines run on the same <code>TestCoroutineScheduler</code>.</p>
<p>For example, we can create our own set of these objects as we did in the example above and pass them to our components as needed, while also passing either the <code>TestCoroutineScheduler</code> or the <code>TestDispatcher</code> to the <code>runTest</code> coroutine builder (won't work with <code>TestScope</code> since <code>CoroutineScope</code> is not a <code>CoroutineContext.Element</code>) if needed:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `my test` = <span class="hljs-title">runTest</span><span class="hljs-params">(testDispatcher)</span></span> {
   ...
}
</code></pre>
<p>But in most cases, it is enough to use the <code>TestScope</code> provided by the <code>runTest</code> coroutine builder, with all its underlying elements.</p>
<p>If we look at the <code>ActivityRepositoryImpl</code> constructor, we need both a <code>CoroutineScope</code> and a <code>CoroutineDispatcher</code>. </p>
<p>Getting a <code>TestScope</code> is quite easy, since the receiver of the <code>runTest</code> coroutine builder is a <code>TestScope</code> that is automatically created for us:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `my test`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = <span class="hljs-keyword">this</span>,
        ....
    )
}
</code></pre>
<p>Passing the <code>CoroutineDispatcher</code> to our repository is a bit trickier since we don't have access to it. However, we do have access to the <code>CoroutineContext</code>. So if you are familiar with how things work in the coroutine world, getting the <code>TestDispatcher</code> is quite straightforward:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `my test`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-keyword">val</span> testDispatcher = coroutineContext[ContinuationInterceptor] <span class="hljs-keyword">as</span> TestDispatcher

    <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = <span class="hljs-keyword">this</span>,
        ioDispatcher = testDispatcher,
        ....
    )
}
</code></pre>
<p>If that line hurts your brain and you have no idea how it works, there are two options.</p>
<p>If you are curious and want to understand what that syntax does, I can refer you to <a target="_blank" href="https://maxkim.eu/things-every-kotlin-developer-should-know-about-coroutines-part-1-coroutinecontext">my article about the <code>CoroutineContext</code></a>.</p>
<p>However, if you think that this is ugly and understandably don't want to see such code again, there is another way we can provide a <code>TestDispatcher</code> to our repository.</p>
<p>As you remember, we have mentioned that the most important part of coroutine testing is the <code>TestCoroutineScheduler</code>. Luckily, a <code>TestScope</code> exposes its scheduler for us to use as we please.</p>
<p>That said, we can just create a new <code>StandardTestDispatcher</code> using the provided <code>TestCoroutineScheduler</code>, which will work just as fine:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `my test`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = <span class="hljs-keyword">this</span>,
        ioDispatcher = StandardTestDispatcher(testScheduler),
        ...
    )
}
</code></pre>
<blockquote>
<p>Note: <code>testScheduler</code> is a property of the <code>TestScope</code>, which is a receiver for <code>runTest</code>.</p>
</blockquote>
<h3 id="heading-test-scenarios">Test scenarios</h3>
<p>Now that we know how to resolve the dependencies, let's write some tests for the following scenarios:</p>
<ol>
<li>Calling <code>getNewActivity()</code> returns a result after switching the context;</li>
<li>Calling <code>getNewActivityInANewCoroutine</code> calls remote data source in a separate coroutine.</li>
</ol>
<p>We can go either with fakes or mocks for these tests, but I prefer creating fakes to have them available and not be too dependent on mocks.</p>
<p>Here are the fakes that I will be using:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeActivityLocalDataSource</span> : <span class="hljs-type">ActivityLocalDataSource {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveActivity</span><span class="hljs-params">(activity: <span class="hljs-type">Activity</span>)</span></span> {
        <span class="hljs-comment">// Save</span>
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">deleteActivity</span><span class="hljs-params">(activity: <span class="hljs-type">Activity</span>)</span></span> {
        <span class="hljs-comment">// Delete</span>
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">isActivitySaved</span><span class="hljs-params">(key: <span class="hljs-type">String</span>)</span></span>: <span class="hljs-built_in">Boolean</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getActivityListLiveData</span><span class="hljs-params">()</span></span>: LiveData&lt;List&lt;Activity&gt;&gt; {
        <span class="hljs-keyword">return</span> MutableLiveData()
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeActivityRemoteDataSource</span> : <span class="hljs-type">ActivityRemoteDataSource {</span></span>

    <span class="hljs-keyword">var</span> getActivityWasCalled = <span class="hljs-literal">false</span>
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">set</span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getActivity</span><span class="hljs-params">()</span></span>: Result&lt;Activity&gt; {
        getActivityWasCalled = <span class="hljs-literal">true</span>
        <span class="hljs-keyword">return</span> Result.Success(activity1)
    }
}
</code></pre>
<p>These fakes are nothing special. We have already covered all the concepts.</p>
<h3 id="heading-first-test-scenario"><strong>First test scenario</strong></h3>
<p>Now that we have done all the preparations, writing the first test should be really easy:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `<span class="hljs-title">getNewActivity</span><span class="hljs-params">()</span></span> returns a result after switching the context`() = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = <span class="hljs-keyword">this</span>,
        ioDispatcher = StandardTestDispatcher(testScheduler),
        remoteDataSource = FakeActivityRemoteDataSource(),
        localDataSource = FakeActivityLocalDataSource()
    )

    <span class="hljs-keyword">val</span> expectedActivity = activity1

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">val</span> result = activityRepository.getNewActivity()

    <span class="hljs-comment">// Assert</span>
    assert(result <span class="hljs-keyword">is</span> Result.Success)
    assertEquals((result <span class="hljs-keyword">as</span> Result.Success).<span class="hljs-keyword">data</span>, expectedActivity)
}
</code></pre>
<h3 id="heading-second-test-scenario"><strong>Second test scenario</strong></h3>
<p>The second scenario is a bit more tricky, but only because I threw in a <code>delay(1000)</code> into the coroutine to illustrate an important concept. Without it, it would be the same test scenario as others where we launch a new coroutine. We would call <code>activityRepository.getNewActivityInANewCoroutine()</code> and either <code>runCurrent()</code> or <code>advanceUntilIdle()</code> immediately after.</p>
<p>However, when we have a <code>delay()</code>, the <code>runCurrent()</code> method will no longer work. </p>
<p>Physically, a <code>runTest</code> block skips all time delays to execute tests immediately in real-time. However, a <code>TestCoroutineScheduler</code> still keeps track of the virtual time, allowing us to test time-sensitive scenarios.</p>
<p>And that is where an important distinction between <code>runCurrent()</code> and <code>advanceUntilIdle()</code> comes in:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Runs the tasks that are scheduled to execute at this moment of virtual time.
 */</span>
<span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">runCurrent</span><span class="hljs-params">()</span></span>
</code></pre>
<p>The <code>runCurrent()</code> function runs all the current tasks without advancing the virtual time.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Runs the enqueued tasks in the specified order, 
 * advancing the virtual time as needed until there are no more
 * tasks associated with the dispatchers linked to this scheduler.
 */</span>
<span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">advanceUntilIdle</span><span class="hljs-params">()</span></span> {
</code></pre>
<p>While the <code>advanceUntilIdle</code> function, as its name implies, will advance the virtual time until there are no more tasks.</p>
<blockquote>
<p>Note: You can use the <code>advanceTimeBy(delayTimeMillis: Long)</code> function to test time-sensitive scenarios.</p>
</blockquote>
<p>With that information in mind, we can now finish writing our test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `getNewActivityInANewCoroutine correctly calls remote <span class="hljs-keyword">data</span> source`<span class="hljs-params">()</span></span> = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> fakeRemoteRepository = FakeActivityRemoteDataSource()
    <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = <span class="hljs-keyword">this</span>,
        ioDispatcher = StandardTestDispatcher(testScheduler),
        remoteDataSource = fakeRemoteRepository,
        localDataSource = FakeActivityLocalDataSource()
    )

    <span class="hljs-comment">// Act</span>
    activityRepository.getNewActivityInANewCoroutine()
    advanceUntilIdle()

    <span class="hljs-comment">// Assert</span>
    assert(fakeRemoteRepository.getActivityWasCalled)
}
</code></pre>
<h2 id="heading-wrapping-up-unit-tests">Wrapping up Unit tests</h2>
<p>We have covered most of the topics that will allow you to write any Unit test from now on.</p>
<p>There are still some untested components left in this project, but we will not explicitly cover them in this article since they will be very similar and repetitive. That said, I will include as many tests as it makes sense to write in the <code>finish</code> branch of <a target="_blank" href="https://github.com/mkims/boredom-buster">the project</a>. So you can check that out for further reference.</p>
<h1 id="heading-writing-integration-tests">Writing Integration tests</h1>
<p>I feel like there is often confusion about what integration tests are. I have seen people confusing them with Android instrumented tests and, if my memory serves me right, it was even mentioned somewhere in Google documentation that integration tests should be run on a real or emulated device.</p>
<p>To clear the air before we move on, integration tests (again, it's in the name!) are <em>testing the integration between two or more components</em> of an application. And that is their main difference from unit tests, which test some local functionality of a component while replacing all dependencies with mocks and fakes. Depending on the test scenario, we can run them either locally or on a device. That said, it can even be argued that if we are testing how our subject under test is interacting with the mocks, it is a small integration test of sorts.</p>
<p>But let's not get bogged down too much with the semantics.</p>
<p>They are not as important as a properly tested application.</p>
<h2 id="heading-testing-how-it-all-works-together">Testing how it all works together</h2>
<p>The information we have already discussed while writing unit tests is more than enough to write almost any test. So in this section, we will use everything we have learned so far and write a test that will test everything from a view model to a data source.</p>
<p>We will be testing that when the <code>loadNewActivity()</code> method is called, the <code>ActivityApiClient</code> appropriately calls its <code>getActivity()</code> method.</p>
<p>The approach here is the same as with the Unit tests we have been writing all this time. The only difference is that most of our dependencies will be <em>real implementations</em>.</p>
<p>That said, we will mock the <code>ActivityApiClient</code> since we already have dedicated tests with MockWebServer for that.</p>
<p>Let's create a new test for <code>NewActivityViewModel</code> in the <code>test</code> folder and call it <code>NewActivityViewModelIntegrationTest</code> to distinguish it from the other test class.</p>
<p>Next, we will create instances of real implementations all the way from the presentation layer to the framework layer, with mocks for <code>ActivityApiClient</code> and <code>ActivityDao</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@ExperimentalCoroutinesApi</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewActivityViewModelIntegrationTest</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> testScheduler = TestCoroutineScheduler()
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> testDispatcher = StandardTestDispatcher(testScheduler)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> testScope = TestScope(testDispatcher)

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> coroutineRule = CoroutineRule(testDispatcher)

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> mockApiClient: ActivityApiClient = mock()
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> mockActivityDao: ActivityDao = mock()

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> remoteDataSource = ActivityRemoteDataSourceImpl(mockApiClient)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> localDataSource = ActivityLocalDataSourceImpl(mockActivityDao)

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> activityRepository = ActivityRepositoryImpl(
        appScope = testScope,
        ioDispatcher = testDispatcher,
        remoteDataSource = remoteDataSource,
        localDataSource = localDataSource
    )

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> getRandomActivity = GetRandomActivityImpl(activityRepository)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> saveActivity = SaveActivityImpl(activityRepository)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> deleteActivity = DeleteActivityImpl(activityRepository)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> isActivitySaved = IsActivitySavedImpl(activityRepository)
}
</code></pre>
<p>To illustrate other options (and avoid creating all the dependencies from scratch for every test), we are creating all the dependencies as properties of our test class. Because of that, we have created our own <code>TestScope</code> and <code>TestDispatcher</code> to pass into the <code>ApplicationRepository</code> since we are not inside a <code>runTest</code> block anymore. That is also a valid approach for providing scopes and dispatchers to components.</p>
<p>However, the most important thing to mention is that we have to pass our newly created <code>testDispatcher</code> to the <code>CoroutineRule</code>. Otherwise, we will have multiple schedulers, and the tests will fail:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@get:Rule</span>
<span class="hljs-keyword">val</span> coroutineRule = CoroutineRule(testDispatcher)
</code></pre>
<p>With all the dependencies set up, writing the test itself can't be any easier:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> `calling <span class="hljs-title">loadNewActivity</span><span class="hljs-params">()</span></span> triggers the api client`() = runTest {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">val</span> viewModel = NewActivityViewModel(
        getRandomActivity,
        saveActivity,
        deleteActivity,
        isActivitySaved
    )

    <span class="hljs-comment">// Act</span>
    viewModel.loadNewActivity()
    runCurrent()

    <span class="hljs-comment">// Assert</span>
    verify(mockApiClient, times(<span class="hljs-number">1</span>)).getActivity()
}
</code></pre>
<p>Now that you know what integration tests are and how to write them, you can write as many as you want for your application. We will not write any more integration tests in this article since they will be repetitive. Still, you can check the <code>finish</code> branch for more examples.</p>
<h1 id="heading-writing-jetpack-compose-ui-tests">Writing Jetpack Compose UI tests</h1>
<p>When I started writing this article, I had no idea how enormous it would become. I would have probably been too lazy to write it if I knew.</p>
<p>That said, we are on the final stretch, so buckle up.</p>
<p>In this section, we will look into how we can write UI tests for Jetpack Compose. </p>
<p>The approach to writing tests for composables is the same as for regular tests. We can write small unit tests, testing composables in isolation, or medium and large integration tests, testing whole screens of the application.</p>
<p>As before, we will start small and cover all the basics so you can comfortably write Compose UI tests on your own.</p>
<p>Before we start, we will need to set up the dependencies.</p>
<p>Android Studio automatically includes the <code>androidx.compose.ui:ui-test-junit4</code> library in the Compose projects, so the only one we need to add to be able to run Compose tests is:</p>
<pre><code class="lang-kotlin">debugImplementation(<span class="hljs-string">"androidx.compose.ui:ui-test-manifest:<span class="hljs-variable">$compose_version</span>"</span>)
</code></pre>
<p>Now, let's open up <code>NewActivityScreen.kt</code> and generate a test for it inside the <code>androidTest</code> folder.</p>
<p>One thing we need to do before we can start writing tests is to add a <code>ComposeTestRule</code>. It allows us to set composable content on the screen of our test device.</p>
<p>For testing composables in isolation, we can create <code>ComposeTestRule</code> using <code>createComposeRule()</code> function:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewActivityScreenTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> composeTestRule = createComposeRule()
}
</code></pre>
<blockquote>
<p>Note: We needed the <code>ui-test-manifest</code> dependency for this rule to work properly.</p>
</blockquote>
<p>We will look at the scenario of how to test a whole <code>Activity</code> (again, the Android one) later on.</p>
<p>Now that we have our <code>ComposeTestRule</code> let's create a simple test that displays a <code>NewActivityCard</code> and asserts that the title is displayed correctly. Luckily, we already have some test <code>Activity</code> models available in the <code>androidTest</code> folder from testing the database.</p>
<p>To start displaying composables on the device we can use:</p>
<pre><code class="lang-kotlin">composeTestRule.setContent {
    <span class="hljs-comment">// Compose world</span>
}
</code></pre>
<p>So let's compose the <code>NewActivityCard</code> in our test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">activityNameDisplayedOnACard</span><span class="hljs-params">()</span></span> {
    composeTestRule.setContent {
        NewActivityCard(
            modifier = Modifier.fillMaxWidth(),
            activity = androidActivity1,
            isFavorite = <span class="hljs-literal">false</span>,
            onFavoriteClick = { },
            onLinkClick = { }
        )
    }
}
</code></pre>
<p>This test will now display a <code>NewActivityCard</code> on the screen.</p>
<p>We can also use the <code>ComposeTestRule</code> to make assertions about our composables. But before we do that, we need to understand the concept of <em>semantics</em> in Compose.</p>
<h2 id="heading-semantics-in-compose">Semantics in Compose</h2>
<p>In Compose, there is a <em>Composition</em> - a tree-like structure that consists of composables that describe the UI. Parallel to that, there is another tree, called <em>the Semantics tree</em>. It describes the UI in an alternative manner. It gives the UI components <em>semantic meaning</em> that makes UI understandable for accessibility features and testing framework.</p>
<p>Another way to put it is that the Composition contains the information on <em>how</em> to draw the UI components, while the semantics tree contains the information about what those components <em>mean</em>.</p>
<p>When testing Jetpack Compose UI, we will be using the Semantics tree to look up components on the screen and make assertions about them. Therefore, it can be beneficial to visualize how the semantic tree looks for the given UI.</p>
<p>We can do it in tests with the help of <code>ComposeTestRule</code>:</p>
<pre><code class="lang-kotlin">composeTestRule.onRoot().printToLog(tag = <span class="hljs-string">"SEMANTICS TREE"</span>)
</code></pre>
<blockquote>
<p>Note: <code>SEMANTICS TREE</code> is just a tag, not a requirement.</p>
</blockquote>
<p>It will print all the information about semantic nodes to the debug level logs.</p>
<p>Here is an example of how the semantics tree looks for our <code>NewActivityCard</code>:</p>
<pre><code class="lang-text">Printing with useUnmergedTree = 'false'
    Node #1 at (l=0.0, t=66.0, r=1080.0, b=878.0)px
     |-Node #2 at (l=0.0, t=66.0, r=1080.0, b=878.0)px
        |-Node #3 at (l=66.0, t=128.0, r=277.0, b=180.0)px
        | Text = '[Recreational]'
        | Actions = [GetTextLayoutResult]
        |-Node #4 at (l=937.0, t=121.0, r=1003.0, b=187.0)px
        | Role = 'Button'
        | Focused = 'false'
        | ContentDescription = '[Save Activity]'
        | Actions = [OnClick]
        | MergeDescendants = 'true'
        |-Node #7 at (l=362.0, t=312.0, r=718.0, b=386.0)px
        | Text = '[Learn to dance]'
        | Actions = [GetTextLayoutResult]
        ...
</code></pre>
<p>As you can see, we can easily understand what individual UI components do.</p>
<p>For example:</p>
<pre><code class="lang-text">|-Node #4 at (l=937.0, t=121.0, r=1003.0, b=187.0)px
| Role = 'Button'
| Focused = 'false'
| ContentDescription = '[Save Activity]'
| Actions = [OnClick]
| MergeDescendants = 'true'
</code></pre>
<p>We have a button here, which we can click on and save our activity. </p>
<blockquote>
<p>Note: If we pass <code>isFavorite = true</code> to our card, the ContentDescription will be <code>[Delete Activity]</code>.</p>
</blockquote>
<p>To use the semantics tree in our tests, <code>ComposeTestRule</code> has a series of <em>finder</em> <code>onNode()</code> methods that return a <code>SemanticsNodeInteraction</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Represents a semantics node and the path to fetch it 
 * from the semantics tree. One can interact with this node 
 * by performing actions such as [performClick], assertions 
 * such as [assertHasClickAction], or navigate to other nodes 
 * such as [onChildren].
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SemanticsNodeInteraction</span></span>
</code></pre>
<p>Here are the examples of <strong><em>assertions</em></strong> we can make on a <code>SemanticsNodeInteraction</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652291863855/1jrfIzTJ9.png" alt="semantics_assert.png" /></p>
<p>And here are the actions we can perform:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652291877649/q0CkExe-9.png" alt="semantics_actions.png" /></p>
<p>To have this information readily available, here is an <a target="_blank" href="https://developer.android.com/images/jetpack/compose/compose-testing-cheatsheet.pdf">awesome Compose testing cheat sheet</a>, prepared by Google.</p>
<p>Now that we understand how to use the semantics tree to write Compose UI tests let's return to our test.</p>
<h2 id="heading-testing-composables-in-isolation">Testing Composables in isolation</h2>
<h3 id="heading-testing-nodes-with-text">Testing nodes with text</h3>
<p>With our first test, we want to assert that the activity name is displayed correctly on the card.</p>
<p>For finding a node with a static text we can use <code>ComposeTestRule</code>'s <code>onNodeWithText()</code> method. After that we will call <code>assertIsDisplayed()</code> on it.</p>
<p>Here is the final test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">activityNameDisplayedOnACard</span><span class="hljs-params">()</span></span> {
    composeTestRule.setContent {
        NewActivityCard(
            modifier = Modifier.fillMaxWidth(),
            activity = androidActivity1,
            isFavorite = <span class="hljs-literal">false</span>,
            onFavoriteClick = { },
            onLinkClick = { }
        )
    }

    composeTestRule.onNodeWithText(androidActivity1.name)
        .assertIsDisplayed()
}
</code></pre>
<h3 id="heading-testing-nodes-with-content-description">Testing nodes with content description</h3>
<p>However, not all UI components will have text on them, so we need other means to access their <code>SemanticsNodeInteraction</code>.</p>
<p>One such example is the favorite button, which allows the user to save or delete an activity.</p>
<p>Let's test that this button triggers the <code>onFavoriteClick</code> function.</p>
<p>As we have discussed previously, for interaction with components, especially lambdas, the easiest route is to use Mockito. So let's use it. </p>
<p>This button doesn't have any text, but it does have a content description. That is another way how we can access a node - with <code>ComposeTestRule</code>'s <code>onNodeWithContentDescription()</code> method.</p>
<p>The content descriptions are stored in the <code>strings.xml</code> file, so we will need a <code>Context</code> to access them. However, we already know how to get a <code>Context</code> in instrumented tests from the previous examples.</p>
<p>With that in mind, here is our final test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onFavoriteClickCallbackIsTriggered</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> onFavoriteClick: (isFavorite: <span class="hljs-built_in">Boolean</span>) -&gt; <span class="hljs-built_in">Unit</span> = mock()
    <span class="hljs-keyword">val</span> isFavorite = <span class="hljs-literal">false</span>

    composeTestRule.setContent {
        NewActivityCard(
            modifier = Modifier.fillMaxWidth(),
            activity = androidActivity1,
            isFavorite = isFavorite,
            onFavoriteClick = onFavoriteClick,
            onLinkClick = { }
        )
    }

    <span class="hljs-keyword">val</span> contentDescription = ApplicationProvider.getApplicationContext&lt;Context&gt;()
        .getString(R.string.cd_save_activity)

    composeTestRule.onNodeWithContentDescription(contentDescription)
        .performClick()

    verify(onFavoriteClick, times(<span class="hljs-number">1</span>)).invoke(!isFavorite)
}
</code></pre>
<h3 id="heading-testing-nodes-with-tags"><strong>Testing nodes with tags</strong></h3>
<p>There is a third option if we can't find our UI components using text or content description.</p>
<p>We can manually add a <code>testTag</code> to our component to find it later. Some people might have a knee-jerk reaction to the notion that we are changing production code to make our tests run, and I would agree with that sentiment.</p>
<p>However, in Jetpack Compose, we sometimes don't have other options, and the toolkit embraces this practice. That's why the <code>ComposeTestRule</code> has a method <code>onNodeWithTag(testTag: String)</code>.</p>
<p>In this test, we will test if clicking a link on the activity card triggers the <code>onLinkClick</code> callback. We obviously can use both text and content description to find this node, but let's pretend we can't and use a <code>testTag</code> to find this node in the semantics tree.</p>
<p>First, let's add a <code>Tags</code> object file to our project (not the <code>androidTest</code> module). And add a tag for our link button:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">object</span> Tags {

    <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> ActivityLink = <span class="hljs-string">"tag_activity_link"</span>
}
</code></pre>
<blockquote>
<p>Note: I am using the Pascal case naming convention for constants since it is used throughout the Compose framework.</p>
</blockquote>
<p>Now let's open the <code>NewActivityScreen.kt</code> file and find our <code>TextButton</code>. It should be somewhere around line 138.</p>
<p>To add a test tag to a composable, we need to use <code>Modifier</code>'s <code>testTag()</code> method:</p>
<pre><code class="lang-kotlin">TextButton(
    modifier = Modifier
        .align(alignment = Alignment.CenterHorizontally)
        .testTag(Tags.ActivityLink),
    onClick = {
        onLinkClick(activity.link)
    }
) {
    ...
}
</code></pre>
<p>And that is it. We can now find this composable as a node in the semantics tree using this tag and use it in our test. All the other concepts should already be familiar.</p>
<p>Here is the finished test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onLinkClickCallbackIsTriggered</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> onLinkClick: (link: String) -&gt; <span class="hljs-built_in">Unit</span> = mock()

    composeTestRule.setContent {
        NewActivityCard(
            modifier = Modifier.fillMaxWidth(),
            activity = androidActivity1,
            isFavorite = <span class="hljs-literal">false</span>,
            onFavoriteClick = { },
            onLinkClick = onLinkClick
        )
    }

    composeTestRule.onNodeWithTag(Tags.ActivityLink)
        .performClick()

    verify(onLinkClick, times(<span class="hljs-number">1</span>)).invoke(androidActivity1.link)
}
</code></pre>
<h2 id="heading-large-ui-compose-tests-with-hilt">Large UI Compose tests with Hilt</h2>
<p>To finish this article with a bang, we will write a large UI test for the whole application. But there is one more crucial part of Android testing that we haven't yet discussed.</p>
<p><em>Testing dependency injection with Hilt.</em></p>
<p>Luckily, we can do that in this test and end on a double bang instead.</p>
<p>Here are the steps that we will replicate with this UI test:</p>
<ul>
<li>Open the app and wait for an activity to load;</li>
<li>Click refresh and wait for a new activity to load;</li>
<li>Click save to favorites;</li>
<li>Go to the Favorites screen and ensure that the saved activity is in the list;</li>
<li>Click delete and ensure that the activity is no longer in the list;</li>
<li>Assert that the "no saved activities" info message is displayed.</li>
</ul>
<p>Moreover, our test will use Hilt to inject dependencies. We will swap the <code>ActivityApiClient</code> for a test <code>ApiClient</code> using the MockWebServer, and the Room database for an in-memory instance.</p>
<h3 id="heading-setting-up-hilt-testing">Setting up Hilt testing</h3>
<p>Let's start by adding Hilt testing dependencies to our project:</p>
<pre><code class="lang-kotlin">androidTestImplementation <span class="hljs-string">"com.google.dagger:hilt-android-testing:<span class="hljs-variable">$hilt_version</span>"</span>
kaptAndroidTest <span class="hljs-string">"com.google.dagger:hilt-android-compiler:<span class="hljs-variable">$hilt_version</span>"</span>
</code></pre>
<p>Now, let's create a new test for <code>BoredomBusterApp.kt</code> Composable.</p>
<p>First, we have to annotate this test with <code>@HiltAndroidTest</code> annotation, which will generate the Hilt components. Second, we need to add a <code>HiltAndroidRule</code> and pass our test instance to it:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@HiltAndroidTest</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BoredomBusterAppTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> hiltRule = HiltAndroidRule(<span class="hljs-keyword">this</span>)
}
</code></pre>
<p>With that out of the way, to use Hilt in tests, we need an <code>Application</code> class that supports Hilt. Since our app doesn't need anything from our own <code>Application</code> class, we can use <code>HiltTestApplication</code> provided by <code>hilt-android-testing</code> library. However, if you need to use a custom application class, there is a solution in <a target="_blank" href="https://developer.android.com/training/dependency-injection/hilt-testing#custom-application">the official documentation</a>.</p>
<p>The next step is to set up a custom runner, which will set up this application for tests. It sounds scary, but it really isn't.</p>
<p>Let's create a new <code>di</code> package inside the <code>androidTest</code> module and add a <code>HiltTestRunner</code> class to it:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HiltTestRunner</span> : <span class="hljs-type">AndroidJUnitRunner</span></span>() {

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">newApplication</span><span class="hljs-params">(
        classLoader: <span class="hljs-type">ClassLoader</span>?, 
        name: <span class="hljs-type">String</span>?, 
        context: <span class="hljs-type">Context</span>?
    )</span></span>: Application {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.newApplication(
            classLoader, 
            HiltTestApplication::<span class="hljs-keyword">class</span>.java.name, 
            context
        )
    }
}
</code></pre>
<p>Now all we have to do is to open the module-level <code>build.gradle</code> file and replace the existing <code>testInstrumentationRunner</code> inside <code>defaultConfig</code> with our new one:</p>
<pre><code class="lang-kotlin">testInstrumentationRunner <span class="hljs-string">"eu.maxkim.boredombuster.di.HiltTestRunner"</span>
</code></pre>
<h3 id="heading-replacing-hilt-modules-for-tests">Replacing Hilt modules for tests</h3>
<p>We have two options if we want to replace the production Hilt bindings with test ones. We can either replace the whole Hilt module containing the bindings or bind fake components for each test individually.</p>
<p>We will discuss the first scenario. However, if you only want to swap bindings for individual tests, it is quite simple to do. For that, refer to <a target="_blank" href="https://developer.android.com/training/dependency-injection/hilt-testing#binding-new">the Hilt testing documentation</a>. But keep in mind that the second approach can noticeably slow down the execution of your tests.</p>
<p>We will start by replacing the <code>DbModule</code> containing <code>AppDatabase</code> and <code>ActivityDao</code> bindings.</p>
<p>Let's create a new object <code>TestDbModule</code> inside the <code>di</code> package we have just created and annotate it with <code>@Module</code>.</p>
<p>Next, we have to specify in which component to install this module, just like we do with <code>@InstallIn</code> in production modules, and specify which module to replace. We can achieve both these goals with the <code>@TestInstallIn</code> annotation, which we can use as follows:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [DbModule::class]
)</span>
<span class="hljs-keyword">object</span> TestDbModule {

}
</code></pre>
<p>Apart from that, it is just a regular Hilt module, and we can just provide our dependencies. We have already looked at how to create an in-memory Room database, so here is the final code:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [DbModule::class]
)</span>
<span class="hljs-keyword">object</span> TestDbModule {

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideRoom</span><span class="hljs-params">(<span class="hljs-meta">@ApplicationContext</span> context: <span class="hljs-type">Context</span>)</span></span>: AppDatabase {
        <span class="hljs-keyword">return</span> Room.inMemoryDatabaseBuilder(
            context,
            AppDatabase::<span class="hljs-keyword">class</span>.java
        ).build()
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideActivityDao</span><span class="hljs-params">(appDatabase: <span class="hljs-type">AppDatabase</span>)</span></span>: ActivityDao {
        <span class="hljs-keyword">return</span> appDatabase.activityDao()
    }
}
</code></pre>
<p>Next, we will replace the <code>NetworkModule</code>. While everything stays the same as when we used the <code>MockWebServer</code> for testing <code>ActivityRemoteDataSourceImpl</code>, we have to make some additional considerations since we will be running our UI test on a real Android system.</p>
<p>Before we start, we need to add the <code>MockWebServer</code> library as a dependency to <code>androidTest</code> module:</p>
<pre><code class="lang-kotlin">androidTestImplementation <span class="hljs-string">"com.squareup.okhttp3:mockwebserver:<span class="hljs-variable">$okhttp_version</span>"</span>
</code></pre>
<p>However, there is one problem. When running a <code>MockWebServer</code> in the instrumented tests, this newer version will conflict with Retrofit's older <code>okhttp3</code> version. I am a bit puzzled why this wasn't an issue when running local tests, but I will think about it some other day.</p>
<p>That said, the easiest way to resolve this problem is to force a newer version of the <code>okhttp</code> library by adding a resolution strategy to the end of the module-level <code>build.gradle</code> file:</p>
<pre><code class="lang-kotlin">dependencies {
    ...
}

configurations.all {
    resolutionStrategy {
        force <span class="hljs-string">"com.squareup.okhttp3:okhttp:<span class="hljs-variable">$okhttp_version</span>"</span>
    }
}
</code></pre>
<p>With that out of the way, the next issue is that the <code>mockWebServer.url("/")</code> method that we used for passing a base URL to the Retrofit is considered a network operation. And as you most certainly are aware, Android restricts using network operations on the main thread.</p>
<p>Switching threads in a Hilt modules is not a trivial matter, so I used the solution provided in <a target="_blank" href="https://medium.com/@jurajkunier/writing-ui-tests-with-dagger-android-and-mockwebserver-aed9564e89b3">this medium article</a>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Provides</span>
<span class="hljs-meta">@Singleton</span>
<span class="hljs-meta">@BaseUrl</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideBaseUrl</span><span class="hljs-params">(mockWebServer:<span class="hljs-type">MockWebServer</span>)</span></span>: String {
    <span class="hljs-keyword">var</span> url = <span class="hljs-string">""</span>
    <span class="hljs-keyword">val</span> thread = Thread {
        url = mockWebServer.url(<span class="hljs-string">"/"</span>).toString()
    }
    thread.start()
    thread.join()
    <span class="hljs-keyword">return</span> url
}
</code></pre>
<p>Now, let's finish our <code>TestNetworkModule</code>, which replaces the <code>NetworkModule</code> and provides an <code>ActivityApiClient</code> that uses the <code>MockWebServer</code>.</p>
<p>Here is the final code:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [NetworkModule::class]
)</span>
<span class="hljs-keyword">object</span> TestNetworkModule {

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideOkHttpClient</span><span class="hljs-params">()</span></span>: OkHttpClient {
        <span class="hljs-keyword">return</span> OkHttpClient.Builder().build()
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideMockServer</span><span class="hljs-params">()</span></span>: MockWebServer {
        <span class="hljs-keyword">return</span> MockWebServer()
    }

    <span class="hljs-comment">/**
     * We need to jump through the hoops a bit
     * to avoid NetworkOnMainThread exception
     * in our UI tests.
     */</span>
    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-meta">@BaseUrl</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideBaseUrl</span><span class="hljs-params">(mockWebServer:<span class="hljs-type">MockWebServer</span>)</span></span>: String {
        <span class="hljs-keyword">var</span> url = <span class="hljs-string">""</span>
        <span class="hljs-keyword">val</span> thread = Thread {
            url = mockWebServer.url(<span class="hljs-string">"/"</span>).toString()
        }
        thread.start()
        thread.join()
        <span class="hljs-keyword">return</span> url
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideMoshi</span><span class="hljs-params">()</span></span>: Moshi {
        <span class="hljs-keyword">return</span> Moshi.Builder().add(ActivityTypeAdapter()).build()
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideRetrofit</span><span class="hljs-params">(
        okHttpClient: <span class="hljs-type">OkHttpClient</span>, 
        moshi: <span class="hljs-type">Moshi</span>, 
        <span class="hljs-meta">@BaseUrl</span> baseUrl: <span class="hljs-type">String</span>
    )</span></span>: Retrofit {
        <span class="hljs-keyword">return</span> Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create(moshi).asLenient())
            .build()
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideApiClient</span><span class="hljs-params">(retrofit: <span class="hljs-type">Retrofit</span>)</span></span>: ActivityApiClient {
        <span class="hljs-keyword">return</span> retrofit.create(ActivityApiClient::<span class="hljs-keyword">class</span>.java)
    }
}
</code></pre>
<p>However, we are not done with network issues in tests yet. But this will be the last one, I promise.</p>
<p>Now the problem is that we are not using any encryption for our <code>MockWebServer</code>, and starting with Android 9, the <a target="_blank" href="https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted">cleartext communication is disabled by default</a> for network security reasons.</p>
<p>Since we don't need this security level for debug builds that UI test use, the easiest fix is to enable cleartext traffic for debug builds while leaving it off for production builds.</p>
<p>To achieve that, we need to create a new <code>/debug</code> folder inside the <code>/src</code> and add a new debug <code>AndroidManifest.xml</code> file, which will be merged with the real one for debug builds.</p>
<p>We only need to change one flag in the debug manifest:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">manifest</span> <span class="hljs-attr">xmlns:android</span>=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
    <span class="hljs-attr">xmlns:tools</span>=<span class="hljs-string">"http://schemas.android.com/tools"</span>
    <span class="hljs-attr">package</span>=<span class="hljs-string">"eu.maxkim.boredombuster"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">application</span> <span class="hljs-attr">android:usesCleartextTraffic</span>=<span class="hljs-string">"true"</span>
        <span class="hljs-attr">tools:ignore</span>=<span class="hljs-string">"MissingApplicationIcon,UnusedAttribute"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">manifest</span>&gt;</span>
</code></pre>
<p>We are now ready to use our test Hilt bindings in UI tests. Hilt will automatically inject them as dependencies where needed.</p>
<p>And if we want to inject a component directly into the test, it works just like in Android components. We can use <code>@Inject</code> annotation with a <code>lateinit</code> property.</p>
<p>However, to populate those properties, we need to call <code>hiltRule.inject()</code>.</p>
<p>Let's add <code>mockWebServer</code> and <code>database</code> instances to our test to see how it works, and clean them up after testing for good measure:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@HiltAndroidTest</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BoredomBusterAppTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>
    <span class="hljs-keyword">val</span> hiltRule = HiltAndroidRule(<span class="hljs-keyword">this</span>)

    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> mockWebServer: MockWebServer

    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> database: AppDatabase

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">init</span><span class="hljs-params">()</span></span> {
        hiltRule.inject()
    }

    <span class="hljs-meta">@After</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">tearDown</span><span class="hljs-params">()</span></span> {
        mockWebServer.shutdown()
        database.close()
    }
}
</code></pre>
<h3 id="heading-preparing-test-models"><strong>Preparing test models</strong></h3>
<p>As we have mentioned before, there are ways to share files between <code>test</code> and <code>androidTest</code> if you want to, but for now, let's create a <code>TestAndroidResponses.kt</code> file in the <code>androidTest</code> module and put some test responses in it:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// TestAndroidResponses.kt</span>
<span class="hljs-keyword">val</span> successfulAndroidResponse1 = <span class="hljs-string">"""
    {
      "activity": "Go to a music festival with some friends",
      "type": "social",
      "participants": 4,
      "price": 0.4,
      "link": "",
      "key": "6482790",
      "accessibility": 0.2
    }
"""</span>.trimIndent()

<span class="hljs-keyword">val</span> successfulAndroidResponse2 = <span class="hljs-string">"""
    {
      "activity": "Learn how to use a french press",
      "type": "recreational",
      "participants": 1,
      "price": 0.3,
      "link": "https://en.wikipedia.org/wiki/French_press",
      "key": "4522866",
      "accessibility": 0.3
    }
"""</span>.trimIndent()
</code></pre>
<p>Also, let's add the parsed versions to our <code>TestAndroidModels.kt</code> file:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// TestAndroidModels.kt</span>
<span class="hljs-keyword">val</span> responseAndroidActivity1 = Activity(
    name = <span class="hljs-string">"Go to a music festival with some friends"</span>,
    type = Activity.Type.Social,
    participantCount = <span class="hljs-number">4</span>,
    price = <span class="hljs-number">0.4f</span>,
    accessibility = <span class="hljs-number">0.2f</span>,
    key = <span class="hljs-string">"6482790"</span>,
    link = <span class="hljs-string">""</span>
)

<span class="hljs-keyword">val</span> responseAndroidActivity2 = Activity(
    name = <span class="hljs-string">"Learn how to use a french press"</span>,
    type = Activity.Type.Recreational,
    participantCount = <span class="hljs-number">1</span>,
    price = <span class="hljs-number">0.3f</span>,
    accessibility = <span class="hljs-number">0.3f</span>,
    key = <span class="hljs-string">"4522866"</span>,
    link = <span class="hljs-string">"https://en.wikipedia.org/wiki/French_press"</span>
)
</code></pre>
<h3 id="heading-testing-compose-activity">Testing Compose Activity</h3>
<p>With all the preparations out of the way, we can now start testing our <code>MainActivity</code>. </p>
<p>For testing composables in isolation we were creating a <code>ComposeTestRule</code> with the <code>createComposeRule()</code> function. </p>
<p>However, we need to create an <code>AndroidComposeTestRule</code> for testing Android activities. We can do it with a handy function <code>createAndroidComposeRule()</code>, which takes an <code>Activity</code> as a type.</p>
<p>We will use that to create our compose rule, but we also want to ensure that the Hilt rule is always applied first. We can do it by adding an <code>order</code> argument to our <code>Rule</code>s.</p>
<p>Here is how our rules look after setting everything up:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@HiltAndroidTest</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BoredomBusterAppTest</span> </span>{

    <span class="hljs-meta">@get:Rule</span>(order = <span class="hljs-number">1</span>)
    <span class="hljs-keyword">val</span> hiltRule = HiltAndroidRule(<span class="hljs-keyword">this</span>)

    <span class="hljs-meta">@get:Rule</span>(order = <span class="hljs-number">2</span>)
    <span class="hljs-keyword">val</span> composeTestRule = createAndroidComposeRule&lt;MainActivity&gt;()

    ...
}
</code></pre>
<p>Now we can finally write the test itself.</p>
<p>When writing large end-to-end UI tests, we usually still test concrete scenarios. But just to illustrate the concept, we will write a test that clicks all over the app and call it a day (finally!).</p>
<p>When using <code>createAndroidComposeRule()</code> we don't need to call <code>setContent()</code> ourselves anymore, since it will create our <code>MainActivity</code> for us.</p>
<p>Another important concept when UI testing the whole app is that we will probably need to wait for stuff to appear.</p>
<p>There is a convenient <code>ComposeTestRule</code> method for that, which we can use to wait until the activity card appears on the screen after loading:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">waitUntil</span><span class="hljs-params">(timeoutMillis: <span class="hljs-type">Long</span>!, condition: (() -&gt; <span class="hljs-type">Boolean</span>)?)</span></span>: <span class="hljs-built_in">Unit</span>
</code></pre>
<p>It will just wait around (not quite, but we will discuss it later) until the given condition is satisfied. We can also specify the timeout after which the test will fail. By default, the timeout is 1000ms.</p>
<p>In our case, after loading a new activity, we will wait around until the node with activity's name appears on the screen. And to make things a bit cleaner, we will extract this logic in a separate method:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">waitUntilVisibleWithText</span><span class="hljs-params">(text: <span class="hljs-type">String</span>)</span></span> {
    composeTestRule.waitUntil {
        composeTestRule.onAllNodesWithText(text)
            .fetchSemanticsNodes().size == <span class="hljs-number">1</span>
    }
}
</code></pre>
<p>This method will just wait around until there is at least one node with the given text.</p>
<p>To make our test more readable, let's extract all the interactions into separate private methods, which we will also be able to use in other tests if we wish.</p>
<p>For example, we can create a method that clicks on a node with a content description:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clickOnNodeWithContentDescription</span><span class="hljs-params">(<span class="hljs-meta">@StringRes</span> cdRes: <span class="hljs-type">Int</span>)</span></span> {
    <span class="hljs-keyword">val</span> contentDescription = ApplicationProvider.getApplicationContext&lt;Context&gt;()
        .getString(cdRes)

    composeTestRule.onNodeWithContentDescription(contentDescription)
        .performClick()
}
</code></pre>
<p>And use it in a bunch of action methods for our test:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveAsFavorite</span><span class="hljs-params">()</span></span> {
    clickOnNodeWithContentDescription(R.string.cd_save_activity)
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">deleteFromFavorites</span><span class="hljs-params">()</span></span> {
    clickOnNodeWithContentDescription(R.string.cd_delete_activity)
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">refreshActivity</span><span class="hljs-params">()</span></span> {
    clickOnNodeWithContentDescription(R.string.cd_refresh_activity)
}
</code></pre>
<p>To add methods for switching between bottom navigation tabs, let's add some new tags:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">object</span> Tags {

    ...
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> ActivityTab = <span class="hljs-string">"tag_activity_tab"</span>
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> FavoritesTab = <span class="hljs-string">"tag_favorites_tab"</span>
}
</code></pre>
<p>And add them to the <code>BottomNavigationBar.kt</code>:</p>
<pre><code class="lang-kotlin">listOf(
    Destination.Activity,
    Destination.Favorites
).forEach { destination -&gt;
    <span class="hljs-keyword">val</span> testTag = <span class="hljs-keyword">when</span> (destination) {
        Destination.Activity -&gt; Tags.ActivityTab
        Destination.Favorites -&gt; Tags.FavoritesTab
        <span class="hljs-keyword">else</span> -&gt; <span class="hljs-string">""</span>
    }
    BottomNavigationItem(
        modifier = Modifier.testTag(testTag),
        ...
</code></pre>
<p>Now we can find these nodes and click on them for navigation:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">navigateToFavorites</span><span class="hljs-params">()</span></span> {
    composeTestRule.onNodeWithTag(Tags.FavoritesTab)
        .performClick()
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">navigateToActivity</span><span class="hljs-params">()</span></span> {
    composeTestRule.onNodeWithTag(Tags.ActivityTab)
        .performClick()
}
</code></pre>
<p>Lastly, let's add a method to enqueue an activity json on our <code>MockWebServer</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">enqueueActivityResponse</span><span class="hljs-params">(activityJson: <span class="hljs-type">String</span>)</span></span> {
    mockWebServer.enqueue(
        MockResponse()
            .setResponseCode(<span class="hljs-number">200</span>)
            .addHeader(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"application/json; charset=utf-8"</span>)
            .setBody(activityJson)
    )
}
</code></pre>
<p>Now we have everything we need to test the scenario outlined at the beginning of this section.</p>
<p>Here is the final test:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">refreshingSavingAndDeletingWorksCorrectly</span><span class="hljs-params">()</span></span> {
    enqueueActivityResponse(successfulAndroidResponse1)
    waitUntilVisibleWithText(responseAndroidActivity1.name)

    enqueueActivityResponse(successfulAndroidResponse2)
    refreshActivity()
    waitUntilVisibleWithText(responseAndroidActivity2.name)

    saveAsFavorite()
    navigateToFavorites()

    composeTestRule.onNodeWithText(responseAndroidActivity2.name)
        .assertIsDisplayed()

    deleteFromFavorites()

    composeTestRule.onNodeWithText(responseAndroidActivity2.name)
        .assertDoesNotExist()

    <span class="hljs-keyword">val</span> noActivitiesMessage = ApplicationProvider.getApplicationContext&lt;Context&gt;()
        .getString(R.string.message_empty_activity_list)

    composeTestRule.onNodeWithText(noActivitiesMessage)
        .assertIsDisplayed()
}
</code></pre>
<h2 id="heading-other-considerations-when-testing-compose">Other considerations when testing Compose</h2>
<p>Jetpack Compose is a huge toolkit, and obviously, we didn't cover every aspect of it when it comes to testing.</p>
<p>However, before we part our ways, here are some pointers that might be useful for testing more complex scenarios with Compose.</p>
<h3 id="heading-using-unmerged-tree">Using unmerged tree</h3>
<p>Sometimes nodes <em>merge together</em> the semantic information about their children, for example, if two <code>Text</code> composables are composed side-by-side.</p>
<p>First of all, remember that you can always see how your semantics tree looks for debugging:</p>
<pre><code class="lang-kotlin">composeTestRule.onRoot().printToLog(<span class="hljs-string">"TAG"</span>)
</code></pre>
<p>Secondly, all the finder methods have a <code>useUnmergedTree</code> argument, which you can use to search the unmerged version of the semantics tree:</p>
<pre><code class="lang-kotlin">composeTestRule.onNodeWithText(<span class="hljs-string">"My Text"</span>, useUnmergedTree = <span class="hljs-literal">true</span>)
    .assertIsDisplayed()
</code></pre>
<h3 id="heading-synchronization">Synchronization</h3>
<p>Just like the test coroutine builder, the Compose doesn't run in real-time during the tests and has a virtual clock.</p>
<p>During tests, when the UI state of a composable changes it doesn't automatically trigger recomposition as it would when running the app normally.</p>
<p>The advancement of virtual clock and recomposition is usually triggered by the assertion methods on a <code>SemanticsNodeInteraction</code>. Likewise, methods like <code>waitUntil</code> will advance the clock frame by frame if the main clock is in the <code>autoAdvance</code> mode. </p>
<p>Speaking of which, if you would like to take manual control of the main clock, you can set <code>autoAdvance</code> to <code>false</code>:</p>
<pre><code class="lang-kotlin">composeTestRule.mainClock.autoAdvance = <span class="hljs-literal">false</span>
</code></pre>
<p>This will allow you to control the main clock manually by using methods like:</p>
<pre><code class="lang-kotlin">composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
</code></pre>
<p>The are some other nuances with synchronization in Compose, so if you are interested in this topic, please refer <a target="_blank" href="https://developer.android.com/jetpack/compose/testing#sync">to the official documentation</a>.</p>
<h3 id="heading-custom-semantic-properties">Custom semantic properties</h3>
<p>You can create your own semantic properties to expose for your tests if you want. You can read about that <a target="_blank" href="https://developer.android.com/jetpack/compose/testing#custom-semantics-properties">in the official documentation</a>.</p>
<h3 id="heading-ui-tests-with-compose-and-views">UI tests with Compose and Views</h3>
<p>If you have a hybrid UI app that uses both Compose and the View system, you can write tests that combine Espresso and <code>ComposeTestRule</code>. No additional setup is needed. You <a target="_blank" href="https://developer.android.com/jetpack/compose/testing#espresso-interop">can just use them together</a> in your tests.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>When I first set out to write this article, I was sure that it would take no more than a couple of evenings. However, it turns out that testing Android applications is quite a big topic, and there is a lot of ground to cover.</p>
<p>Hopefully, I have discussed the most common scenarios, and this information is a good start for writing all kinds of tests for your Android apps.</p>
<p>Once again, you can find everything that we have talked about <a target="_blank" href="https://github.com/mkims/boredom-buster">on GitHub</a> in the <code>finish</code> branch. I will throw some more tests in there as well for reference.</p>
<p>If you have any questions about testing or Android development in general, or if you think I missed some crucial aspects of testing, feel free to leave your comments. I would appreciate the feedback.</p>
<p>See you next time.</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Things every Kotlin Developer should know about Coroutines. Part 5: Cancellation.]]></title><description><![CDATA[As much as we had talked about cancellation in the last part, in this article, we will often touch upon exception handling. Since, as discussed previously, these two concepts use the same mechanism.
That said, cancellation in the coroutines library i...]]></description><link>https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-5-cancellation</link><guid isPermaLink="true">https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-5-cancellation</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Fri, 14 Jan 2022 17:00:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1642174453234/N3eNVc3gR.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As much as we had talked about cancellation in the last part, in this article, we will often touch upon exception handling. Since, as discussed previously, these two concepts use the same mechanism.</p>
<p>That said, cancellation in the coroutines library is not as straightforward as it might seem. Misusing it can produce subtle bugs and puzzle developers unfamiliar with its inner workings.</p>
<p>So let’s get cracking.</p>
<h2 id="heading-cancelling-a-coroutine">Cancelling a coroutine</h2>
<p>Like with exception propagation, cancellation in coroutines is managed by a <code>Job</code>. Moreover, cancellation is nothing more than throwing a <code>CancellationException</code>. The critical distinction here is that if a coroutine throws a <code>CancellationException</code>, it is considered to have been <em>cancelled normally</em>, while any other exception is considered <em>a failure</em>.</p>
<p>Another difference is that while a regular exception in a child coroutine will trigger the cancellation of its parent (unless it’s using a <code>SupervisorJob</code>), the <code>CancellationException</code> will not.</p>
<p>Now, let’s see how that works in practice.</p>
<p>First of all, a <code>Job</code> is our handle to a coroutine, and it has a lifecycle. If you are not familiar with the lifecycle of a <code>Job</code>, please refer to the <a target="_blank" href="https://maxkim.eu/things-every-kotlin-developer-should-know-about-coroutines-part-4-exception-handling">Part 4</a> of this series.</p>
<p>We can cancel a coroutine by calling the <code>.cancel()</code> function on its <code>Job</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Cancels this job with an optional cancellation[cause].
 * A cause can be used to specify an error message 
 * or to provide other details on
 * the cancellation reason for debugging purposes.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">cancel</span><span class="hljs-params">(cause: <span class="hljs-type">CancellationException</span>? = <span class="hljs-literal">null</span>)</span></span>
</code></pre>
<p>You can also specify a cause for cancellation, but it has to be a subtype of the <code>CancellationException</code> and, therefore, it will always lead to normal cancellation.</p>
<p>When you call <code>.cancel()</code> on a <code>Job</code>, it triggers the following events:</p>
<ul>
<li>The <code>Job</code> goes into the <strong>Cancelling</strong> state and cannot be used as a parent to new coroutines or do suspending work anymore;</li>
<li><em>At the first suspension point that cooperates with cancellation</em> (or after manually calling <code>ensureActive()</code>, more on that later), a <code>CancellationException</code> is thrown, prompting the cancellation of all children, but not its parent;</li>
<li>After all the children are cancelled, the <code>Job</code> moves to the <strong>Cancelled</strong> state.</li>
</ul>
<blockquote>
<p>Both <code>CoroutineScope</code> and <code>CoroutineContext</code> have an extension function <code>.cancel(cause: CancellationException? = null)</code>.  These functions just get a <code>Job</code> from the corresponding context and call <code>.cancel(cause)</code> on that.</p>
</blockquote>
<p>Here is a simple example of how cancellation works:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    <span class="hljs-keyword">val</span> parentJob = scope.launch {
        println(<span class="hljs-string">"Starting the parent job!"</span>)

        launch {
            <span class="hljs-keyword">while</span> (isActive) {
                delay(<span class="hljs-number">10</span>)
                println(<span class="hljs-string">"Doing some work..."</span>)
            }
        }.invokeOnCompletion {
            println(<span class="hljs-string">"Cancelling all work! "</span>)
        }
    }

    parentJob.invokeOnCompletion {
        println(<span class="hljs-string">"The parent job is cancelled!"</span>)
    }

    delay(<span class="hljs-number">50</span>)

    parentJob.cancel()

    <span class="hljs-comment">// Take note of this delay!!!</span>
    delay(<span class="hljs-number">100</span>)

    println(<span class="hljs-string">"Main is done!"</span>)
}

Output: 
Starting the parent job!
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Cancelling all work! 
The parent job <span class="hljs-keyword">is</span> cancelled!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>We have a parent coroutine with a long-running child coroutine in this example. After some time, we cancel the <code>parentJob</code>, which cancels both parent and child coroutines as expected.</p>
<p>However, as we now know, calling <code>.cancel()</code> doesn't stop a <code>Job</code> dead in its tracks but only triggers the beginning of cancellation. Therefore if we removed the <code>delay(100)</code> after cancelling our job, we would get the following output:</p>
<pre><code class="lang-kotlin">Starting the parent job!
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Main <span class="hljs-keyword">is</span> done! &lt;- This <span class="hljs-keyword">is</span> printed immediately!
Cancelling all work! 
The parent job <span class="hljs-keyword">is</span> cancelled!
</code></pre>
<p>“Main is done!” is printed immediately after calling <code>.cancel()</code> because the parent <code>runBlocking</code> coroutine will continue its execution, while the cancellation of the <code>parentJob</code> will proceed asynchronously.</p>
<p>In this case, we are lucky that cancellation is almost immediate, and we get all the messages printed out. However, since our parent coroutine is not a child of <code>runBlocking</code>, the structured concurrency principle does not apply, and the <code>runBlocking</code> coroutine will not wait for the cancellation to complete.</p>
<p>If we are not careful with such cancellations, it could lead <em>to subtle bugs and race conditions</em>.</p>
<p>That said, we have used the <code>.delay()</code> function for illustration purposes only. It is a horrible solution to this problem in actual code.</p>
<p>The proper way to wait for a <code>Job</code>’s completion is to call <code>job.join()</code>.</p>
<p>The <code>.join()</code> function will suspend the calling coroutine until the joined <code>Job</code> is fully completed. Keep in mind that <code>.join()</code> will always continue normally, regardless of how the joined <code>Job</code> has been completed, as long as the <code>Job</code> of the calling coroutine is active.</p>
<p>Here is how the proper cancellation of the <code>parentJob</code> in our example would look like:</p>
<pre><code class="lang-kotlin">parentJob.cancel()
parentJob.join()

println(<span class="hljs-string">"Main is done!"</span>)
</code></pre>
<p>Moreover, this is such a common practice in coroutines that the library offers an extension function <code>Job.cancelAndJoin()</code>, which does precisely that - calls <code>.cancel()</code> and <code>.join()</code> immediately afterward.</p>
<pre><code class="lang-kotlin">parentJob.cancelAndJoin()

println(<span class="hljs-string">"Main is done!"</span>)
</code></pre>
<p>By calling <code>cancelAndJoin(),</code> we are cancelling our job and suspending the calling coroutine until the job has finished all the cancellation work.</p>
<h2 id="heading-understanding-suspension-points">Understanding suspension points</h2>
<p>As stated earlier, the <code>CancellationException</code> is generally thrown at the first suspension point that cooperates with cancellation.</p>
<p>While a suspension point doesn’t necessarily mean your code will automatically cooperate with cancellation, all <code>suspend</code> functions (with one exception that I am aware of, which we will discuss in a bit) from the coroutines library are safe to cancel. Therefore, it is crucial to quickly identify them in your code to avoid redundant cooperation with cancellation.</p>
<p>The easiest way to identify suspension points is with help from the IDE. If you are writing Kotlin code, chances are you are using an IntelliJ IDEA based IDE, in which case suspension points are conveniently displayed in the gutter:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642174491408/iUJLchjFP.png" alt="suspension_points.png" /></p>
<p>IntelliJ IDEA marks every call to a <code>suspend</code> function with a special arrow symbol.</p>
<p>While every <code>suspend</code> function in the coroutines library is a valid suspension point and is cancellable, marking your own functions with the <code>suspend</code> modifier does not mean it will necessarily suspend a coroutine or make it cancellable.</p>
<p>Here is an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doStuff</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"I do stuff!"</span>)
}
</code></pre>
<p>This function does not have any suspension points, and the IDE will warn you about the redundant <code>suspend</code> modifier. That said, if you call this function, the IDE will display the suspension symbol in the gutter regardless.</p>
<h3 id="heading-for-every-rule-there-is-an-exception">For every rule, there is an exception</h3>
<p>While the example above doesn’t support cancellation because we wrote a lousy <code>suspend</code> function, there is a case when cancellation is not supported by a suspending function from the coroutines library by design.</p>
<p>This exception is the <code>suspendCoroutine</code> function. Diving deep into the specifics of this function is out of the scope of this article. Still, it suspends current execution and runs a non-suspend block, allowing to explicitly continue the coroutine execution with a series of callbacks.</p>
<p>This functionality is needed to bridge the suspending world with other asynchronous solutions. However, there is a better function for that, which we will discuss in a minute.</p>
<p>For now, let’s take a look at this example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> job: Job = scope.launch {
        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
            doStuff()
        }
    }

    delay(<span class="hljs-number">5</span>)

    println(<span class="hljs-string">"Cancelling the job!"</span>)
    job.cancelAndJoin()

    println(<span class="hljs-string">"Main is done!"</span>)
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doStuff</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// this is proper suspension point</span>
    <span class="hljs-comment">// but it will not throw a</span>
    <span class="hljs-comment">// CancellationException</span>
    suspendCoroutine&lt;<span class="hljs-built_in">Unit</span>&gt; { continuation -&gt;
        continuation.resume(<span class="hljs-built_in">Unit</span>)
    }
    println(<span class="hljs-string">"I do stuff!"</span>)
}
</code></pre>
<p>If we run this code, we will get:</p>
<pre><code>...
I do stuff<span class="hljs-operator">!</span>
I do stuff<span class="hljs-operator">!</span>
I do stuff<span class="hljs-operator">!</span>
...
<span class="hljs-comment">// Forever and ever, since we have </span>
<span class="hljs-comment">// joined the job after cancel</span>
</code></pre><p>This job will never get cancelled, and the <code>runBlocking</code> coroutine will continue waiting indefinitely since we have joined the cancelled <code>Job</code>.</p>
<p>This function is not cancellable because there is a very similar function - <code>suspendCancellableCoroutine</code>, which, as its name suggests, supports cancellation while providing the same functionality.</p>
<p>Here is the adjusted <code>doStuff()</code> function:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doStuff</span><span class="hljs-params">()</span></span> {
    suspendCancellableCoroutine&lt;<span class="hljs-built_in">Unit</span>&gt; { continuation -&gt;
        continuation.resume(<span class="hljs-built_in">Unit</span>)
    }
    println(<span class="hljs-string">"I do stuff!"</span>)
}
</code></pre>
<p>Now, if we rerun the code, we will get a desired and predictable outcome:</p>
<pre><code>...
I do stuff<span class="hljs-operator">!</span>
I do stuff<span class="hljs-operator">!</span>
Cancelling the job<span class="hljs-operator">!</span>
I do stuff<span class="hljs-operator">!</span>
I do stuff<span class="hljs-operator">!</span>
...
Main <span class="hljs-keyword">is</span> done<span class="hljs-operator">!</span>
</code></pre><p>In this case, a <code>suspendCancellableCoroutine</code> will throw a <code>CancellationException</code> at its suspension point as soon as the <code>Job</code> gets cancelled, just as it should.</p>
<blockquote>
<p>We can also achieve the same correct cancellation behavior by calling any other <code>suspend</code> function from the coroutines library (or that cooperates with cancellation), for example, <code>delay(1)</code>.</p>
</blockquote>
<p>Because of this behavior, there is little reason to use <code>suspendCoroutine</code> - a <code>suspendCancellableCoroutine</code> is always a safer option. Apart from cooperation with cancellation, <code>suspendCancellableCoroutine</code> provides a <code>invokeOnCancellation { }</code> callback that can be used to clean up resources.</p>
<p>That said, given that these functions are primarily used to write adapters to other asynchronous libraries, you will probably never use them. Almost all adapters you would ever need are already provided by either the coroutines team or the libraries' authors.</p>
<p>However, it is still important to be aware of this behavior for learning purposes.</p>
<h2 id="heading-cooperating-with-cancellation">Cooperating with cancellation</h2>
<p>While <code>suspend</code> functions coming from the coroutines library are safe to cancel, you should always think about cooperating with cancellation when writing your own code.</p>
<p>There are a couple of ways to do that.</p>
<h3 id="heading-checking-the-state-of-a-job">Checking the state of a Job</h3>
<p>One way to make your code cancellable is to explicitly check the current <code>Job</code>'s state.</p>
<p>The most convenient way to do this is by using the <code>CoroutineScope.isActive</code> extension property.</p>
<p>We have done it numerous times in examples throughout this series with <code>while (isActive)</code> loops.</p>
<p>Example:</p>
<pre><code class="lang-kotlin">scope.launch {
    <span class="hljs-comment">// a periodical work</span>
    <span class="hljs-keyword">while</span> (isActive) {
        <span class="hljs-comment">// do work</span>
        delay(<span class="hljs-number">1000</span>)
    }
}
</code></pre>
<p>There is a similar extension <code>CoroutineContext.isActive</code>, which works exactly the same way. Both these functions check the <code>isActive</code> property on the underlying <code>Job</code>.</p>
<p>Also, keep in mind that you can also check the <code>isCancelled</code> property if you have a reference to the <code>Job</code>. However, in most cases it is redundant and there are no corresponding extension functions for either <code>CoroutineScope</code> or <code>CoroutineContext</code>.</p>
<h3 id="heading-ensureactive">ensureActive()</h3>
<p>Another common way to check for cancellation is to call <code>ensureActive()</code>, which is an extension function available for <code>Job</code>,  <code>CoroutineScope</code>, and <code>CoroutineContext</code>.</p>
<p>This function is a great option for cases where you would otherwise write a <code>if (isActive)</code> statement. Moreover, under the hood <code>ensureActive</code> does just that, but it also throws a <code>CancellationException</code> for good measure:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> Job.<span class="hljs-title">ensureActive</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> {
    <span class="hljs-keyword">if</span> (!isActive) <span class="hljs-keyword">throw</span> getCancellationException()
}
</code></pre>
<blockquote>
<p>Note: This function uses <code>getCancellationException()</code> to include the original cause of cancellation.</p>
</blockquote>
<p>Just like the <code>isActive</code> check, <code>ensureActive()</code> is mostly used inside coroutines.</p>
<p>Example:</p>
<pre><code class="lang-kotlin">scope.launch { 
    <span class="hljs-comment">// a long running for loop</span>
    <span class="hljs-comment">// without suspension points</span>
    <span class="hljs-keyword">for</span> (item <span class="hljs-keyword">in</span> items) {
        ensureActive()
        println(<span class="hljs-string">"Processing item..."</span>)
    }
}
</code></pre>
<p>Alternatively, you can use <code>ensureActive()</code> on a <code>coroutineContext</code> inside <code>suspend</code> functions, since, as opposed to checking <code>isActive</code>, it throws a <code>CancellationException</code> and will stop the execution:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doSomeWork</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// do some work</span>
    coroutineContext.ensureActive()
    <span class="hljs-comment">// do some more work</span>
}
</code></pre>
<h3 id="heading-yield">yield()</h3>
<blockquote>
<p>From the documentation: Yields the thread (or thread pool) of the current coroutine dispatcher to other coroutines on the same dispatcher to run if possible.</p>
</blockquote>
<p>The purpose of the <code>yield()</code> function is to free up the current thread to allow other coroutines to run on it. In practice, it suspends current execution and immediately resumes it.</p>
<blockquote>
<p>In general, any suspended coroutine is not guaranteed to resume running on the same thread if the dispatcher allows it.</p>
</blockquote>
<p>It can be beneficial to use <code>yield()</code> during CPU heavy work or during work that can exhaust the thread pool.</p>
<p>However, it is also common practice to use <code>yield()</code> to cooperate with cancellation.</p>
<p>Example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doHeavyWork</span><span class="hljs-params">()</span></span> {
    withContext(Dispatchers.Default) {
        repeat(<span class="hljs-number">1000</span>) {
            yield()
            <span class="hljs-comment">// do heavy work</span>
        }
    }
}
</code></pre>
<p>It can also be used in coroutines instead of <code>ensureActive()</code> if you need the added benefit of yielding the thread.</p>
<h2 id="heading-cleaning-up">Cleaning up</h2>
<p>Sometimes you have to clean up resources when a coroutine is cancelled. Luckily, it is quite easy, since cancellation throws a <code>CancellationException</code> and like any other exception, we can catch it in a <code>try-catch</code> block and do necessary clean up in a <code>finally</code> block.</p>
<p>However, before we discuss cleaning up in more detail, I want to address a common mistake that can be overlooked when using a <code>try-catch</code> block in coroutines.</p>
<h3 id="heading-interrupted-cancellation">Interrupted cancellation</h3>
<p>Take a look at the following example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> job = scope.launch {
        <span class="hljs-keyword">try</span> {
            println(<span class="hljs-string">"Doing work..."</span>)
            delay(<span class="hljs-built_in">Long</span>.MAX_VALUE)
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            println(<span class="hljs-string">"The work was interrupted!"</span>)
        }

        println(<span class="hljs-string">"How am I still running?"</span>)
    }

    delay(<span class="hljs-number">100</span>)

    job.cancelAndJoin()

    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Doing work...
The work was interrupted!
How am I still running?
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>As you see, even though we cancel our <code>Job</code>, it still completes until the end.</p>
<p>Let’s break down why this happens.</p>
<p>When we call <code>job.cancelAndJoin()</code> the job goes into the <strong>Cancelling</strong> state, and since at that moment the coroutine is suspended by <code>delay(Long.MAX_VALUE)</code>, which is a cancellable <code>suspend</code> function, this suspension point throws a <code>CancellationException</code>.</p>
<p>Since it is a sub-type of <code>Exception</code>, we catch it inside the <code>try-catch</code> block and <em>handle it manually</em>.</p>
<p>After that, the coroutine will continue its execution, albeit in the <strong>Cancelling</strong> state. It means that for it to throw another <code>CancellationException</code>, it <em>has to reach another suspension point</em>. And given that in our example we don’t have any after the <code>try-catch</code> block, and we don’t explicitly check for cancellation, the coroutine will run all the way until the end.</p>
<p>This is a consequence of managing explicit cancellation with exceptions, and we have to be aware of this.</p>
<p>If we know that our coroutine can be explicitly cancelled and we are using a <code>try-catch</code> block, the common practice is to always rethrow a <code>CancellatonException</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">try</span> {
    println(<span class="hljs-string">"Doing work..."</span>)
    delay(<span class="hljs-built_in">Long</span>.MAX_VALUE)
} <span class="hljs-keyword">catch</span> (e: Exception) {
    println(<span class="hljs-string">"The work was interrupted!"</span>)
    <span class="hljs-keyword">if</span> (e <span class="hljs-keyword">is</span> CancellationException) {
        <span class="hljs-keyword">throw</span> e
    }
}
</code></pre>
<p>With this adjustment in place, our coroutine will get cancelled as expected:</p>
<pre><code>Output:
Doing work...
The work was interrupted<span class="hljs-operator">!</span>
Main <span class="hljs-keyword">is</span> done<span class="hljs-operator">!</span>
</code></pre><h3 id="heading-tools-for-cleaning-up">Tools for cleaning up</h3>
<p>With that little detail out of the way, let’s take a look at how we can go about cleaning up resources after cancellation.</p>
<p>If we need to do clean up in case of a cancellation only, we can catch a <code>CancellationException</code> and do necessary work inside the <code>catch</code> block:</p>
<pre><code class="lang-kotlin">
<span class="hljs-keyword">try</span> {
    println(<span class="hljs-string">"Doing work..."</span>)
    delay(<span class="hljs-built_in">Long</span>.MAX_VALUE)
} <span class="hljs-keyword">catch</span> (e: CancellationException) {
    <span class="hljs-comment">// do clean up</span>
    <span class="hljs-comment">// and don't forget to rethrow the CancellationException</span>
    <span class="hljs-keyword">throw</span> e
}
</code></pre>
<p>Alternatively, we can do clean up regardless of the outcome, using a <code>finally</code> block:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">try</span> {
    println(<span class="hljs-string">"Doing work..."</span>)
    delay(<span class="hljs-built_in">Long</span>.MAX_VALUE)
} <span class="hljs-keyword">finally</span> {
    <span class="hljs-comment">// do clean up</span>
}
</code></pre>
<p>That said, there is a catch (as there always seems to be with the coroutines library).</p>
<p>At this point, our <code>Job</code> is in the <strong>Cancelling</strong> state, which means it can no longer suspend execution. Therefore, any attempt to call a <code>suspend</code> function, for example, inside the <code>finally</code> block, will throw another <code>CancellationException</code>. Still, we might need to run some suspending functions as a part of a clean-up logic after cancellation.</p>
<p>Luckily, the coroutines library has a tool that allows doing just that - a special <code>Job</code> called <code>NonCancellable</code>.</p>
<p>The <code>NonCancellable</code> job is <em>always active</em> and is designed for use with the <code>withContext</code> function to handle cases as described above. <code>withContext(NonCancellable)</code> will switch to this non-cancellable job before checking for cancellation. Therefore it can be called even from a cancelled coroutine.</p>
<p>That said, let’s summarise everything we have learned about cleaning up with the following example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> job = scope.launch {
        <span class="hljs-keyword">try</span> {
            println(<span class="hljs-string">"Doing work..."</span>)
            delay(<span class="hljs-built_in">Long</span>.MAX_VALUE)
        } <span class="hljs-keyword">catch</span> (e: CancellationException) {
            println(<span class="hljs-string">"The work was cancelled!"</span>)
            <span class="hljs-keyword">throw</span> e
        } <span class="hljs-keyword">finally</span> {
            withContext(NonCancellable) {
                delay(<span class="hljs-number">1000</span>)
                println(<span class="hljs-string">"Did some suspending clean up"</span>)
            }

            println(<span class="hljs-string">"Clean up is done!"</span>)
        }

        println(<span class="hljs-string">"I will never be printed..."</span>)
    }

    delay(<span class="hljs-number">100</span>)

    job.cancelAndJoin()

    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Doing work...
The work was cancelled!
<span class="hljs-comment">// delaying 1 sec</span>
Did some suspending clean up
Clean up <span class="hljs-keyword">is</span> done!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>A word of caution, however. Since <code>NonCancellable</code> is a <code>Job</code>, it can be used as a part of any <code>CoroutineContext</code> given its flexible API. But it was designed for use with the <code>withContext</code> function only. So using it with coroutine builders <code>launch</code> or <code>async</code> (you should never use any <code>Job</code> there anyways, as described in  <a target="_blank" href="https://maxkim.eu/things-every-kotlin-developer-should-know-about-coroutines-part-3-structured-concurrency">Part 3</a>  of this series) will break structured concurrency in every possible way and should never be done.</p>
<h2 id="heading-cancellation-after-a-timeout">Cancellation after a timeout</h2>
<p>In some cases, you might want to cancel some work after a timeout. For that, the coroutines library provides a very convenient function <code>withTimeout</code>. Here’s its declaration:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">withTimeout</span><span class="hljs-params">(timeMillis: <span class="hljs-type">Long</span>, block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>)</span></span>: T
</code></pre>
<p>It runs a suspending block, and after a specified timeout, it throws a <code>TimeoutCancellationException</code>, a subtype of <code>CancellationException</code>.</p>
<p>There is also a less aggressive version of this function - <code>withTimeoutOrNull</code>, which after a specified timeout, cancels its block and returns <code>null</code> without throwing an exception.</p>
<p>These functions <em>are suspending scope functions</em> by nature. They provide a scope just like <code>coroutineScope</code>, <code>supervisorScope</code>, and <code>withContext</code> functions. To be more specific, it will behave exactly like a <code>coroutineScope</code> function, only with a timeout.</p>
<p>Example:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    launch {
        <span class="hljs-keyword">try</span> {
            withTimeout(<span class="hljs-number">100</span>) {
                delay(<span class="hljs-number">400</span>)
            }
        } <span class="hljs-keyword">catch</span> (e: TimeoutCancellationException) {
            println(<span class="hljs-string">"The coroutine has timed out!"</span>)
        }
    }
}

Output:
The coroutine has timed <span class="hljs-keyword">out</span>!
</code></pre>
<p>When using the <code>withTimeout</code> function, after the timeout, <em>it will cancel the parent coroutine</em> (which will also cancel all its children) if the exception wasn’t explicitly handled. If you want other behavior or a better clean-up logic without using <code>try-catch</code>, consider using <code>withTimeoutOrNull</code> instead.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The concept of cooperative cancellation is not something we have to deal with often in other asynchronous solutions. Therefore, it might prove challenging to newcomers and seasoned developers alike.</p>
<p>Neglecting basic principles of cooperative cancellation can lead to memory leaks, wasted resources, and subtle bugs. Because of that, it might seem that it is too much hassle for a feature that shouldn’t be that complicated.</p>
<p>And it is a fair point. The coroutines library has quite a steep learning curve.</p>
<p>However, in my opinion, the resulting API of launching coroutines and elegant solution to establishing parent-child relationships is something that JetBrains deserve an applaud for, and it is a fair trade-off, all things considered.</p>
<p>That said, I have a couple of topic ideas for the next part of this series, but I will have to sleep on that, so no promises.</p>
<p>See you next time.</p>
<p>Your friend,</p>
<p>Max</p>
]]></content:encoded></item><item><title><![CDATA[Things every Kotlin Developer should know about Coroutines. Part 4: Exception Handling.]]></title><description><![CDATA[In Part 3, we have discussed structured concurrency, which was introduced to the coroutines library primarily as a solution to exception handling and cancellation.
Because of that, these two concepts go hand in hand, and even though we will not focus...]]></description><link>https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-4-exception-handling</link><guid isPermaLink="true">https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-4-exception-handling</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Android]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Wed, 05 Jan 2022 19:28:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1641408624827/vd__E1NQR.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Part 3, we have discussed structured concurrency, which was introduced to the coroutines library primarily as a solution to exception handling and cancellation.</p>
<p>Because of that, these two concepts go hand in hand, and even though we will not focus on cancellation just yet, we will inevitably mention it throughout this article since both of them share the same mechanism.</p>
<p>That mechanism is a <code>Job</code>. It enforces structured concurrency by creating parent-child relationships between coroutines and manages exception propagation and cancellation.</p>
<p>Therefore, before talking about exception handling, we should understand what a <code>Job</code> is and how it works.</p>
<h2 id="heading-lifecycle-of-a-job">Lifecycle of a Job</h2>
<p>A <code>Job</code> is an entity with a lifecycle that acts as a handle to a coroutine. Every coroutine's <code>Job</code> goes through several states that culminate in its completion.</p>
<p>The lifecycle of a <code>Job</code> looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641408692383/ccM2_BG6N.png" alt="job-lifecycle-white-01.png" /></p>
<p>A  <code>Job</code> has six states which fall under three main categories:</p>
<ol>
<li>Initial state - <strong>New</strong>, <strong>Active</strong></li>
<li>Transient state - <strong>Completing</strong>, <strong>Cancelling</strong></li>
<li>Final state - <strong>Completed</strong>, <strong>Cancelled</strong></li>
</ol>
<p>A launched coroutine immediately goes into the <strong>Active</strong> state, unless an optional parameter  <code>start = CoroutineStart.LAZY</code> is passed to the coroutine builder, in which case it starts in the <strong>New</strong> state.</p>
<p>A <code>Job</code> in the <strong>New</strong> state can be started and moved to the <strong>Active</strong> state by either calling <code>job.start()</code> or <code>job.join()</code>.</p>
<p>When a coroutine has finished its work, it goes to the <strong>Completing</strong> state, where it <em>awaits the completion of all its children</em> - which, as you now know, is an integral part of the structured concurrency principle.</p>
<p>If an exception or cancellation happens during either the <strong>Active</strong> or <strong>Completing</strong> state, the <code>Job</code> moves to the <strong>Cancelling</strong> state, where it <em>awaits the cancellation of all its children</em>.</p>
<p>After all the children have finished or are cancelled, the <code>Job</code> moves to either the <strong>Completed</strong> or <strong>Cancelled</strong> state.</p>
<blockquote>
<p>Note that these states are not publicly exposed. To find out the state of a <code>Job</code> we can use public properties <code>isActive</code>, <code>isCancelled</code>, and <code>isCompleted</code>.</p>
</blockquote>
<h2 id="heading-exception-propagation">Exception propagation</h2>
<p>Now that we understand the lifecycle of a <code>Job</code>, let’s talk about exception propagation. It works as follows:</p>
<ol>
<li>If a child coroutine fails, it propagates the exception to its parent.</li>
<li>The parent cancels itself and consequently cancels all its children. The parent will wait in the <strong>Cancelling</strong> state until all the children are cancelled.</li>
<li>The parent propagates the exception up to its parent or throws the exception if it is a root coroutine and the exception was not caught.</li>
</ol>
<p>Both exception propagation and cancellation work the same way. Moreover, both are just cancellation with a <code>cause</code> of type <code>Throwable</code>, where an explicit cancellation by the user throws a <code>CancellationException</code>, which gets special treatment.</p>
<p>The actual implementation of this mechanism is quite complex, but here is an example from the source code for illustration:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/** 
 * ...
 * Returns `true` if exception is handled, `false` otherwise 
 * (then caller is responsible for handling an exception)
 * ...
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">open</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">childCancelled</span><span class="hljs-params">(cause: <span class="hljs-type">Throwable</span>)</span></span>: <span class="hljs-built_in">Boolean</span> {
    <span class="hljs-keyword">if</span> (cause <span class="hljs-keyword">is</span> CancellationException) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
    <span class="hljs-keyword">return</span> cancelImpl(cause) &amp;&amp; handlesException
}
</code></pre>
<p>Whenever a child coroutine is cancelled, the parent first checks whether it was cancelled with a <code>CancellationException</code>, in which case it returns <code>true</code>, meaning that the exception is handled and there is nothing more to do. Otherwise, it will process and propagate the exception.</p>
<p>Let’s see, how it works in practice:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    <span class="hljs-comment">// Main Job</span>
    scope.launch {
        <span class="hljs-comment">// Child 1</span>
        launch {
            <span class="hljs-keyword">while</span> (isActive) { 
                <span class="hljs-comment">// run</span>
            }
        }.printOnComplete(<span class="hljs-string">"Child 1 is cancelled!"</span>)

        <span class="hljs-comment">// Child 2</span>
        launch {
            delay(<span class="hljs-number">500</span>)
            println(<span class="hljs-string">"Here goes boom..."</span>)
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"Boom!"</span>)
        }.printOnComplete(<span class="hljs-string">"Child 2 is cancelled!"</span>)
    }.printOnComplete(<span class="hljs-string">"Main Job has completed!"</span>)

    <span class="hljs-comment">// Random coroutine on the same scope</span>
    scope.launch {
        <span class="hljs-keyword">while</span> (isActive) { 
            <span class="hljs-comment">// run</span>
        }
    }.printOnComplete(<span class="hljs-string">"Random coroutine is cancelled!"</span>)

    delay(<span class="hljs-number">1000</span>)
}
</code></pre>
<blockquote>
<p>Note: <code>printOnComplete</code> is a custom extension function for brevity.</p>
</blockquote>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> Job.<span class="hljs-title">printOnComplete</span><span class="hljs-params">(message: <span class="hljs-type">String</span>)</span></span> {
    invokeOnCompletion {
        println(message)
    }
}
</code></pre>
<p>In this example, we launch a new coroutine inside a <code>CoroutineScope</code>. This main coroutine has two children, one of which runs while the coroutine is active, and the second throws an exception after a small delay. There is also a random independent coroutine running in the same scope.</p>
<p>If we run this code, the output will print:</p>
<pre><code class="lang-text">Output:
Here goes boom...
Child 1 is cancelled!
Child 2 is cancelled!
Random coroutine is cancelled!
Exception in thread "DefaultDispatcher-worker-2" 
java.lang.IllegalArgumentException: Boom!
    ...
Main Job has completed!
</code></pre>
<p>This is how standard exception propagation looks like.</p>
<blockquote>
<p>Note: Uncaught exceptions will get passed to the thread’s default exception handler. On JVM it will be just logged to the console, like in this case, while, for example, in Android it will crash the application.</p>
</blockquote>
<p>In this case, an exception in the Child 2 was propagated all the way up to the scope, triggering cancellation of the whole coroutine tree.</p>
<p>However, keep in mind that <em>coroutines have to be cancellable for error propagation to work correctly</em>.</p>
<p>If we change the code of one of the children to something like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Child 1</span>
launch {
    <span class="hljs-comment">// we have changed isActive to true</span>
    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) { 
        <span class="hljs-comment">// run</span>
    }
}.printOnComplete(<span class="hljs-string">"Child 1 cancelled!"</span>)
</code></pre>
<p>And run the code again, we will get:</p>
<pre><code class="lang-text">Here goes boom...
Random coroutine is canceled!
Child 2 is canceled!
</code></pre>
<p>And that’s it. </p>
<p>The exception will never get thrown by the parent coroutine. As we have discussed before, <em>a parent coroutine always waits for its children to complete</em>. However, because we have introduced an infinite loop inside the Child 1, it will never complete and the parent will keep waiting indefinitely, or in this case while the <code>main</code> is running.</p>
<p>That said, the problem here is not the infinite <code>while (true)</code> loop itself, but the fact that this child coroutine <em>is not cooperating with cancellation</em> - a topic we will discuss in Part 5 of this series.</p>
<h2 id="heading-job-vs-supervisorjob">Job vs SupervisorJob</h2>
<p>In the example above, the whole scope was cancelled because one of the children threw an exception. In many cases however, this behavior is undesirable. We would probably want all the other independent coroutines in the same scope to continue running.</p>
<p>This is where a <code>SupervisorJob</code> comes into play. You might have noticed that in the example above we have used a <code>Job()</code> inside the scope’s <code>CoroutineContext</code>. A regular <code>Job</code> cancels itself and propagates exceptions all the way to the top level, while <code>SupervisorJob</code> relies on coroutines to handle their own exceptions and doesn't cancel other coroutines.</p>
<blockquote>
<p>From the documentation: A failure or cancellation of a child does not cause the supervisor job to fail and does not affect its other children.</p>
</blockquote>
<p>That said, <em>uncaught exceptions will always be thrown</em> regardless of the Job implementation.</p>
<p>Incidentally, the implementation of the <code>SupervisorJob</code> is very simple. It overrides a single function from the regular <code>Job</code> implementation:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SupervisorJobImpl</span></span>(parent: Job?) : JobImpl(parent) {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">childCancelled</span><span class="hljs-params">(cause: <span class="hljs-type">Throwable</span>)</span></span>: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">false</span>
}
</code></pre>
<p>This is the same function we looked at earlier. In a <code>SupervisorJob</code> it always returns <code>false</code>, meaning that the exception is not handled and coroutines should handle exceptions themselves.</p>
<p>For this reason, in Part 2 we have mentioned that in most cases it makes sense to use a <code>SupervisorJob()</code> in a top-level scope. This way it won’t get cancelled as soon as one of its children throws an exception.</p>
<p>The same goes for suspending scope builders - a <code>coroutineScope</code> will go down with its children, while a <code>supervisorScope</code> will not.</p>
<p>Here is an example with a <code>coroutineScope</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> result = coroutineScope {
        launch {
            delay(<span class="hljs-number">100</span>)
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"A total fiasco!"</span>)
        }

        launch {
            delay(<span class="hljs-number">200</span>)
            println(<span class="hljs-string">"Hi there!"</span>)
        }

        <span class="hljs-string">"Result!"</span>
    }

    println(<span class="hljs-string">"Got result: <span class="hljs-variable">$result</span>"</span>)
}

Output:
Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"main"</span> java.lang.IllegalArgumentException: A total fiasco!
 ...
</code></pre>
<p>And the same example with a <code>supervisorScope</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> result = supervisorScope {
        launch {
            delay(<span class="hljs-number">100</span>)
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"A total fiasco!"</span>)
        }

        launch {
            delay(<span class="hljs-number">200</span>)
            println(<span class="hljs-string">"Hi there!"</span>)
        }

        <span class="hljs-string">"Result!"</span>
    }

    println(<span class="hljs-string">"Got result: <span class="hljs-variable">$result</span>"</span>)
}

Output:
Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"main"</span> java.lang.IllegalArgumentException: A total fiasco!
 ...
Hi there!
Got result: Result!
</code></pre>
<h2 id="heading-a-special-case-of-an-async-builder">A special case of an Async builder</h2>
<p>Different coroutine builders treat exception propagation differently. While <code>launch</code> automatically propagates exceptions when they are thrown, the <code>async</code> coroutine builder is a little bit special in that regard.</p>
<p>When an exception is thrown inside the <code>async</code> builder that is used as a <em>root coroutine</em> it will rely on the user <em>to consume the exception</em>. </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    <span class="hljs-keyword">val</span> deferred = scope.async {
        delay(<span class="hljs-number">50</span>)
        <span class="hljs-keyword">throw</span> IllegalStateException(<span class="hljs-string">"Async Boom!"</span>)
    }

    delay(<span class="hljs-number">100</span>)

    println(<span class="hljs-string">"I'm done"</span>)
}

Output:
I<span class="hljs-string">'m done</span>
</code></pre>
<p>The exception in this case will never be thrown. It will only be thrown when <code>.await()</code> is called on the <code>Deferred</code> result:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    <span class="hljs-keyword">val</span> deferred = scope.async {
        delay(<span class="hljs-number">50</span>)
        <span class="hljs-keyword">throw</span> IllegalStateException(<span class="hljs-string">"Async Boom!"</span>)
    }

    delay(<span class="hljs-number">100</span>)

    <span class="hljs-comment">// the exception will be thrown here</span>
    deferred.await()

    println(<span class="hljs-string">"I'm done"</span>)
}

Output:
Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"main"</span> java.lang.IllegalStateException: Async Boom!
</code></pre>
<blockquote>
<p>Note: <code>Deferred</code> is just a <code>Job</code> that returns a result.</p>
</blockquote>
<p>The <code>async</code> builder will also behave the same way when used inside a <code>supervisorScope</code>, since a <code>supervisorScope</code> will not notify its parent about exceptions and will rely on children to handle them. In other words, coroutines inside a <code>supervisorScope</code> can be treated as root coroutines.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    scope.launch {
        supervisorScope {
            println(<span class="hljs-string">"I am the supervisor scope!"</span>)

            <span class="hljs-keyword">val</span> deferred = async {
                delay(<span class="hljs-number">50</span>)
                <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"Async Boom!"</span>)
            }

            println(<span class="hljs-string">"Supervisor scope done!"</span>)
        }
    }

    delay(<span class="hljs-number">200</span>)
    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
I am the supervisor scope!
Supervisor scope done!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>And just like in the example with the root <code>async</code> builder, the <code>async</code> exception inside the <code>supervisorScope</code> will be thrown only if <code>.await()</code> is called.</p>
<blockquote>
<p>Note: When using <code>async</code> as a child coroutine or inside a <code>coroutineScope</code>, the exception will be thrown without calling <code>.await()</code> and immediately propagated to the parent, even if wrapped in <code>try-catch</code>.</p>
</blockquote>
<h2 id="heading-handling-exceptions">Handling exceptions</h2>
<p>Now that we understand how exception propagation works in the coroutines library, let’s talk about the most important part - handling thrown exceptions.</p>
<p>For that you have a couple of options.</p>
<h3 id="heading-try-catch">try-catch</h3>
<p>The most straightforward way to handle exceptions is with a <code>try-catch</code> block like you would anywhere else in your code. This way the exceptions get handled immediately without triggering exception propagation and cancellation:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    scope.launch {
        launch {
            <span class="hljs-keyword">try</span> {
                delay(<span class="hljs-number">10</span>)
                <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"A complete failure!"</span>)
            } <span class="hljs-keyword">catch</span> (e: Exception) {
                println(<span class="hljs-string">"Child 1 has recovered from: <span class="hljs-subst">${e.message}</span>"</span>)
            }
        }

        launch {
            delay(<span class="hljs-number">50</span>)
            println(<span class="hljs-string">"Child 2 is OK!"</span>)
        }
    }

    delay(<span class="hljs-number">100</span>)

    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Child <span class="hljs-number">1</span> has recovered from: A complete failure!
Child <span class="hljs-number">2</span> <span class="hljs-keyword">is</span> OK!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>That said, keep in mind that in cases described in the previous section, the <code>async</code> builder will throw exceptions only when <code>.await()</code> is called, and it should be wrapped with <code>try-catch</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    supervisorScope {
        <span class="hljs-keyword">val</span> deferred = async {
            delay(<span class="hljs-number">50</span>)
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"An utter collapse!"</span>)
        }

        <span class="hljs-keyword">try</span> {
            deferred.await()
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            println(<span class="hljs-string">"Supervisor has recovered from: <span class="hljs-subst">${e.message}</span>"</span>)
        }

        println(<span class="hljs-string">"Supervisor scope is done!"</span>)
    }

    delay(<span class="hljs-number">100</span>)
    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Supervisor has recovered from: An utter collapse!
Supervisor scope <span class="hljs-keyword">is</span> done!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<h3 id="heading-runcatching">runCatching</h3>
<p>For more idiomatic Kotlin, you can use <code>runCatching</code> function that comes from Kotlin’s standard library. All it does under the hood, is wraps a block of code in <code>try-catch</code> and returns a <code>Result&lt;R&gt;</code> wrapper:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T, R&gt;</span> T.<span class="hljs-title">runCatching</span><span class="hljs-params">(block: <span class="hljs-type">T</span>.() -&gt; <span class="hljs-type">R</span>)</span></span>: Result&lt;R&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
        Result.success(block())
    } <span class="hljs-keyword">catch</span> (e: Throwable) {
        Result.failure(e)
    }
}
</code></pre>
<p>Here is an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    launch {
        delay(<span class="hljs-number">10</span>)

        <span class="hljs-keyword">val</span> result = runCatching {
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"An absolute disaster!"</span>)
        }

        <span class="hljs-keyword">when</span> {
            result.isSuccess -&gt; println(<span class="hljs-string">"I got: <span class="hljs-subst">${result.getOrNull()}</span>"</span>)
            result.isFailure -&gt; println(<span class="hljs-string">"I have recovered from: <span class="hljs-subst">${result.exceptionOrNull()?.message}</span>"</span>)
        }
    }

    delay(<span class="hljs-number">100</span>)

    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
I have recovered from: An absolute disaster!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<h3 id="heading-coroutineexceptionhandler">CoroutineExceptionHandler</h3>
<p>You might remember that in Part 1 of this series we briefly mentioned the <code>CoroutineExceptionHandler</code> - a context <code>Element</code> that processes uncaught exceptions in coroutines. Now it’s time to discuss it in more detail.</p>
<p>The main difference between handling exceptions with a <code>CoroutineExceptionHandler</code> and a <code>try-catch</code> block is that when an exception gets to a <code>CoroutineExceptionHandler</code> the coroutine <em>had already completed</em> and you can <em>no longer recover</em> from the exception. That is why a <code>CoroutineExceptionHandler</code> should be used as a last-resort measure for exceptions that hadn't been handled differently.</p>
<p>The <code>CoroutineExceptionHandler</code> <em>will only work if it is added to the context of either a <code>CoroutineScope</code> or a root coroutine</em>. Adding it to child coroutines will have no effect, since they will automatically propagate exceptions to their parent. The exception here (no pun intended) are the coroutines that are launched directly inside a <code>supervisorScope</code>, since they are responsible for handling their own exceptions.</p>
<p>Here are some examples:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> handler = CoroutineExceptionHandler { coroutineContext, throwable -&gt;
    println(<span class="hljs-string">"Handler has caught: <span class="hljs-subst">${throwable.message}</span>"</span>)
}

<span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    <span class="hljs-comment">// we are adding a handler to the</span>
    <span class="hljs-comment">// context of a root coroutine</span>
    scope.launch(handler) {
        delay(<span class="hljs-number">10</span>)
        <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"An awful crash!"</span>)
    }

    delay(<span class="hljs-number">100</span>)
    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Handler has caught: An awful crash!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>As an alternative we could have added the <code>handler</code> to our scope directly:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
</code></pre>
<p>In which case there would be no need to add it every time to the context of a root coroutine. That said, if you are using a predefined scope you might not have this option.</p>
<p>As we have mentioned earlier, we can also use a <code>CoroutineExceptionHandler</code> inside a <code>supervisorScope</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> handler = CoroutineExceptionHandler { coroutineContext, throwable -&gt;
    println(<span class="hljs-string">"Handler has caught: <span class="hljs-subst">${throwable.message}</span>"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    supervisorScope {
        launch(handler) {
            delay(<span class="hljs-number">10</span>)
            <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"A shocking mishap!"</span>)
        }
    }

    delay(<span class="hljs-number">100</span>)
    println(<span class="hljs-string">"Main is done!"</span>)
}

Output:
Handler has caught: A shocking mishap!
Main <span class="hljs-keyword">is</span> done!
</code></pre>
<p>However, this use case is quite rare and in most cases other error handling solutions will make more sense.</p>
<h2 id="heading-things-to-keep-in-mind">Things to keep in mind</h2>
<h3 id="heading-suppressed-exceptions">Suppressed exceptions</h3>
<p>One thing to keep in mind is that if multiple children fail with an exception,  <em>the first thrown exception will get propagated</em>, while others exceptions will get attached to it as suppressed exceptions:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> scope = CoroutineScope(Job() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Unit</span> = runBlocking {
    scope.launch {
        launch {
            delay(<span class="hljs-number">100</span>)
            <span class="hljs-keyword">throw</span> IllegalStateException(<span class="hljs-string">"First Boom!"</span>)
        }

        launch {
            delay(<span class="hljs-number">100</span>)
            <span class="hljs-keyword">throw</span> IllegalStateException(<span class="hljs-string">"Second Boom!"</span>)
        }
    }
    delay(<span class="hljs-number">500</span>)
}

Output:
Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"DefaultDispatcher-worker-2"</span> 
java.lang.IllegalStateException: First Boom!
 ...
 Suppressed: java.lang.IllegalStateException: Second Boom!
 ...
</code></pre>
<h3 id="heading-jobs-invokeoncompletion">Job’s invokeOnCompletion</h3>
<p>You can add an <code>invokeOnCompletion</code> callback to a <code>Job</code> to see if there were exceptions during its execution:</p>
<pre><code class="lang-kotlin">job.invokeOnCompletion { throwable -&gt;
    <span class="hljs-keyword">when</span> (throwable) {
        <span class="hljs-keyword">is</span> CancellationException -&gt; println(<span class="hljs-string">"Job was cancelled!"</span>)
        <span class="hljs-keyword">is</span> Throwable -&gt; println(<span class="hljs-string">"Job failed with exception!"</span>)
        <span class="hljs-literal">null</span> -&gt; println(<span class="hljs-string">"Job completed normally!"</span>)
    }
}
</code></pre>
<p>However, keep in mind that if you catch the exception with a <code>try-catch</code> block, it will not get passed to this callback. </p>
<h3 id="heading-cancellationexception">CancellationException</h3>
<p><code>CancellationException</code>s  will not get passed to a <code>CoroutineExceptionHandler</code>, therefore it should not be be relied upon as a resource clean-up mechanism.</p>
<p>For example, a common source of bugs in Android is using a <code>CoroutineExceptionHandler</code> to revert the state of UI in case of an exception inside a <code>ViewModel</code>. In most cases, there is nothing wrong with that, but keep in mind that in that case explicitly cancelling your coroutines might result in a broken UI state.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Handling exceptions in coroutines is not a straightforward task and will require some practice to get hold of all the concepts it envelops. Frankly, for me it was one of the most confusing parts about the coroutines library.</p>
<p>The most important part about all of this, once again, is to understand structured concurrency. Then, in my experience, it all magically clicks into place.</p>
<p>In the next part, we will tackle a sibling of exception handling - cancellation, which should be a breeze now that we understand the underlying mechanisms.</p>
<p>See you then.</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Things every Kotlin Developer should know about Coroutines. Part 3: Structured Concurrency.]]></title><description><![CDATA[If you watch a coroutines video dated before their stable launch in Kotlin 1.3, you might notice that the way coroutines were used in their "experimental" phase is a bit different from now.
For example, at KotlinConf 2017, in his Introductions to Cor...]]></description><link>https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-3-structured-concurrency</link><guid isPermaLink="true">https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-3-structured-concurrency</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[coroutines]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Thu, 23 Dec 2021 12:54:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1640266242099/8Rq97l9AG.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you watch a coroutines video dated before their stable launch in Kotlin 1.3, you might notice that the way coroutines were used in their "experimental" phase is a bit different from now.</p>
<p>For example, at KotlinConf 2017, in his <a target="_blank" href="https://youtu.be/_hfBv0a09Jc?t=1094">Introductions to Coroutines</a>, Roman Elizarov presented a simple code snippet on how to launch a coroutine:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// fire and forget a coroutine! 🚀</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">postItem</span><span class="hljs-params">(item: <span class="hljs-type">Item</span>)</span></span> {
    launch {
        <span class="hljs-keyword">val</span> token = requestToken()
        <span class="hljs-keyword">val</span> post = createPost(token, item)
        proccessPost(post)
    }
}
</code></pre>
<p>Nowadays, this code won't even compile because not long before its stable release, the coroutines library underwent a major design shift called <em>Structured Concurrency</em>.</p>
<h2 id="heading-understanding-structured-concurrency">Understanding Structured Concurrency</h2>
<p>If you are coming from Part 2 of this series, you should already understand structured concurrency and why we need it. However, let’s recap and elaborate on this concept, so everyone is on the same page.</p>
<p>The idea behind structured concurrency is quite simple, regardless of how intimidating it might sound. It requires every coroutine to <em>run in a defined scope</em> that manages a parent-child relationship between coroutines.</p>
<p>This achieves a couple of things:</p>
<ul>
<li>Coroutines are always accounted for and never leak resources;</li>
<li>Parent coroutines always wait for children to complete, which makes concurrency predictable;</li>
<li>Exceptions are always propagated and never lost;</li>
<li>Cancellation is easy and doesn't require passing cancellation tokens to children like many other asynchronous solutions.</li>
</ul>
<p>Here is an example of structured concurrency:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> mainJob = scope.launch {
        println(<span class="hljs-string">"Starting the main job!"</span>)

        launch {
            <span class="hljs-keyword">while</span> (isActive) {
                delay(<span class="hljs-number">10</span>)
                println(<span class="hljs-string">"I am child 1!"</span>)
            }
        }

        launch {
            <span class="hljs-keyword">while</span> (isActive) {
                delay(<span class="hljs-number">20</span>)
                println(<span class="hljs-string">"I am child 2!"</span>)
            }
        }
    }
    mainJob.invokeOnCompletion {
        println(<span class="hljs-string">"The main job is completed/cancelled!"</span>)
    }

    delay(<span class="hljs-number">50</span>)

    <span class="hljs-comment">// this will cancel the main coroutine</span>
    <span class="hljs-comment">// and all its children</span>
    scope.cancel()

    delay(<span class="hljs-number">500</span>)
    println(<span class="hljs-string">"Finishing main()..."</span>)
}

Output:
Starting the main job!
I am child <span class="hljs-number">1</span>!
I am child <span class="hljs-number">2</span>!
I am child <span class="hljs-number">1</span>!
I am child <span class="hljs-number">1</span>!
I am child <span class="hljs-number">2</span>!
I am child <span class="hljs-number">1</span>!
The main job <span class="hljs-keyword">is</span> completed/cancelled!
Finishing main()...
</code></pre>
<p>Among other things, structured concurrency allows cancelling all running coroutines and their children easily. This is just an illustration of this concept, and we will dive deep into cancellation in Part 5 of this series.</p>
<h2 id="heading-the-legacy-woes">The legacy woes</h2>
<p>However, given that structured concurrency was a pretty late addition to the coroutines, some legacy woes <a target="_blank" href="https://elizarov.medium.com/structured-concurrency-anniversary-f2cc748b2401">still haunt</a> the developers of the coroutines library, while confusing less experienced adopters.</p>
<p>One such woe is the <code>GlobalScope</code>. As we have discussed in Part 2, it doesn't have a <code>Job</code> attached to it, and coroutines launched inside the <code>GlobalScope</code> will not adhere to the structured concurrency principle.</p>
<p>It was introduced as an “easy way” to migrate from the legacy unstructured way of launching coroutines as described in the introduction of this article to the version of the coroutines library where launching a coroutine requires a scope.</p>
<p>In Kotlin 1.5, <code>GlobalScope</code> was marked with <code>@DelicateCoroutinesApi</code> annotation to discourage developers from using it. Moreover, JetBrains <a target="_blank" href="https://youtu.be/Mj5P47F6nJg?t=3102">are planning to remove this API altogether</a> in later releases as a part of gradual removal of APIs that allow for <em>unstructured concurrency</em>.</p>
<p>Here is an example, where we attempt to use the <code>GlobalScope</code> as we would a normal scope:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@OptIn(DelicateCoroutinesApi::class)</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    GlobalScope.launch {
        <span class="hljs-keyword">while</span> (isActive) {
            delay(<span class="hljs-number">10</span>)
            println(<span class="hljs-string">"I'm running!"</span>)
        }
    }

    delay(<span class="hljs-number">100</span>)

    println(<span class="hljs-string">"Cancelling GlobalScope!"</span>)
    GlobalScope.cancel()

    delay(<span class="hljs-number">500</span>)
}
</code></pre>
<p>Even though this code looks like it makes sense, running it will throw an exception:</p>
<pre><code class="lang-kotlin">IllegalStateException: Scope cannot be cancelled 
because it does not have a job: kotlinx.coroutines.<span class="hljs-symbol">GlobalScope@</span><span class="hljs-number">1</span>a93a7ca
</code></pre>
<p>The <code>GlobalScope</code> doesn't allow for a structured way to manage its coroutines. It has to be done manually, which is tedious and error-prone.</p>
<p>Another legacy woe is the flexibility of the <code>CoroutineContext</code>, which, as you now know, mirrors a functionality of a map and doesn't impose any restrictions on how you can use it. </p>
<p><a target="_blank" href="https://github.com/Kotlin/kotlinx.coroutines/issues/1001">Here</a> is a very informative GitHub issues thread that illustrates one of the problems this can lead to.</p>
<p>Let’s take a look at the example from that thread (with minor tweaks):</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> = runBlocking {
    <span class="hljs-keyword">val</span> childJob = Job()

    <span class="hljs-keyword">val</span> mainJob = scope.launch {
        println(<span class="hljs-string">"Starting the main job!"</span>)
        launch(childJob) {
            <span class="hljs-keyword">while</span> (isActive) {
                delay(<span class="hljs-number">100</span>)
                println(<span class="hljs-string">"Scope is active: <span class="hljs-subst">${scope.isActive}</span>"</span>)
            }
        }
    }
    mainJob.invokeOnCompletion {
        println(<span class="hljs-string">"The main job is completed/cancelled!"</span>)
    }

    scope.cancel()

    delay(<span class="hljs-number">500</span>)
    println(<span class="hljs-string">"Finishing main()..."</span>)
}
</code></pre>
<p>Taking into account the philosophy behind structured concurrency, one might assume that cancelling the <code>scope</code> in this example will cancel both the <code>mainJob</code> and the <code>childJob</code>.</p>
<p>However, if we run the code:</p>
<pre><code class="lang-text">Starting the main job!
The main job is completed/cancelled!
Scope is active: false
Scope is active: false
Scope is active: false
Scope is active: false
Finishing main()...
</code></pre>
<p>As you can see, structured concurrency is not a very rigid concept. We can easily break it (<em>in most cases unintentionally</em>), given the very flexible API of the coroutines library.</p>
<p>However, the behavior demonstrated in this example is <em>intentional</em> - by introducing a new <code>Job</code> into the <code>coroutineContext</code>, we explicitly override the parent-child relationship.</p>
<p>That said, in the above-mentioned GitHub thread, Roman Elizarov has provided <a target="_blank" href="https://github.com/Kotlin/kotlinx.coroutines/issues/1001#issuecomment-814261687">two very good rules of thumb</a> to make using coroutines predictable and avoid unintentional leaks and behaviors:</p>
<ol>
<li>When using a <code>CoroutineContext</code> you should <strong>not</strong> have a <code>Job</code> there.</li>
<li>When using a <code>CoroutineScope</code> you should <strong>always</strong> have a <code>Job</code> there.</li>
</ol>
<blockquote>
<p>The above rules are slightly edited to improve readability.</p>
</blockquote>
<p>He admitted that if they had designed the coroutines library today, they would have restricted this API. And at the moment he doesn't have a good solution for this problem, except for following the rules as mentioned above.</p>
<h2 id="heading-structured-concurrency-in-practice">Structured concurrency in practice</h2>
<p>By following the recommendations outlined in this series, beginners won't get in trouble when using coroutines and won't break structured concurrency. However, when writing their own coroutine APIs, more advanced developers must know how to follow the principles of structured concurrency in practice.</p>
<p>In the following section, I would like to discuss an example from Android’s lifecycle library and illustrate this point. You don't have to be familiar with Android to follow this example since my goal is to demonstrate a case of broken structured concurrency, not focus on Android’s APIs.</p>
<p>This example might seem quite advanced for some readers, but if this is the case, at least be aware that these considerations exist, and even engineers at Google sometimes stumble when designing coroutines APIs.</p>
<h3 id="heading-the-story-of-a-broken-api">The story of a broken API</h3>
<blockquote>
<p>The full story is outlined in <a target="_blank" href="https://medium.com/androiddevelopers/repeatonlifecycle-api-design-story-8670d1a7d333">this article by Manuel Vivo</a>.</p>
</blockquote>
<p>In Android, we have to be constantly aware of the lifecycle of our UI components since they can be destroyed and recreated quite often. Because of that, we need a robust solution that doesn't leak resources when using coroutines from such components.</p>
<p>One of these solutions provided by the lifecycle library is <code>repeatOnLifecycle</code>, which can be used as follows:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> viewModel <span class="hljs-keyword">by</span> viewModels&lt;MyViewModel&gt;()

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiStateFlow.collect {
                    <span class="hljs-comment">// Collect ui state </span>
                }
            }
        }

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.someOtherFlow.collect {
                    <span class="hljs-comment">// Collect some other data </span>
                }
            }
        }
    }
}
</code></pre>
<p>In this example, <code>lifecycleScope</code> is a scope provided by the lifecycle library. It follows the lifecycle of the given <code>LifecycleOwner</code>. If you are an Android developer and want to know why we cannot rely on that alone or on <code>lifecycleScope.launchWhenStarted { ... }</code> when collecting flows, you can refer to <a target="_blank" href="https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda">this article</a>.</p>
<p>As you can see, this API is quite cumbersome. If we need to collect from multiple flows, we have to launch a new coroutine for each one since <code>collect</code> will suspend the coroutine it runs in. At first glance, it looks like boilerplate and can be improved with Kotlin’s extension functions.</p>
<p>Following the same logic, in one of the alphas of the lifecycle library, Google had introduced the <code>LifecycleOwner.addRepeatingJob</code> API, which looked like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> LifecycleOwner.<span class="hljs-title">addRepeatingJob</span><span class="hljs-params">(
    state: <span class="hljs-type">Lifecycle</span>.<span class="hljs-type">State</span>,
    coroutineContext: <span class="hljs-type">CoroutineContext</span> = EmptyCoroutineContext,
    block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">Unit</span>
)</span></span>: Job = lifecycleScope.launch(coroutineContext) {
    repeatOnLifecycle(state, block)
}
</code></pre>
<p>It hid the boilerplate and allowed for a seemingly cleaner code:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> viewModel <span class="hljs-keyword">by</span> viewModels&lt;MyViewModel&gt;()

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)

        <span class="hljs-comment">// AppCompatActivity is a LifecycleOwner</span>
        addRepeatingJob(Lifecycle.State.STARTED) {
            viewModel.uiStateFlow.collect {
                <span class="hljs-comment">// Collect ui state </span>
            }
        }

        addRepeatingJob(Lifecycle.State.STARTED) {
            viewModel.someOtherFlow.collect {
                <span class="hljs-comment">// Collect some other data </span>
            }
        }
    }
}
</code></pre>
<p>However, if we look deeper, this API is quite problematic. It can <em>break structured concurrency</em> and introduce subtle bugs.</p>
<p>While <code>repeatOnLifecycle</code> is a regular <em>suspending</em> function, the <code>addRepeatingJob</code> is a <em>non-suspending</em> <em>function that launches a new independent coroutine</em> in the <code>lifecycleScope</code>. Still,  developers might be tempted to write code like this: </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> job = lifecycleScope.launch {
    addRepeatingJob(Lifecycle.State.STARTED) {
        viewModel.someDataFlow.collect {
            <span class="hljs-comment">// Collect some data</span>
        }
    }
}

<span class="hljs-comment">// ...if something went wrong</span>
job.cancel()
</code></pre>
<p>If you understand how structured concurrency works, you know what will happen.</p>
<p>The <code>someDataFlow.collect { }</code> will not get cancelled after <code>job.cancel()</code> is called, although that would be a developer’s intention.</p>
<p>Here is how this example would look in a simplified code for better understanding:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    runBlocking {
        <span class="hljs-keyword">val</span> mainJob = scope.launch {
            println(<span class="hljs-string">"Starting the main job!"</span>)
            <span class="hljs-comment">// this is an independent coroutine,</span>
            <span class="hljs-comment">// not a child coroutine</span>
            scope.launch {
                <span class="hljs-keyword">while</span> (isActive) {
                    delay(<span class="hljs-number">100</span>)
                    println(<span class="hljs-string">"I'm alive!!!"</span>)
                }
            }
        }
        mainJob.invokeOnCompletion {
            println(<span class="hljs-string">"The main job is completed/cancelled!"</span>)
        }

        delay(<span class="hljs-number">100</span>)

        mainJob.cancel()

        delay(<span class="hljs-number">500</span>)
        println(<span class="hljs-string">"Finishing main()..."</span>)
    }
}

Output:
Starting the main job!
The main job <span class="hljs-keyword">is</span> completed/cancelled!
I<span class="hljs-string">'m alive!!!
I'</span>m alive!!!
I<span class="hljs-string">'m alive!!!
I'</span>m alive!!!
I<span class="hljs-string">'m alive!!!
Finishing main()...</span>
</code></pre>
<blockquote>
<p>Similar to the example where we introduced a new <code>Job</code> into the context, there is no parent-child relationship between these two coroutines, which might not be immediately apparent to less experienced developers.</p>
</blockquote>
<p>Because of this issue, Google <em>removed</em> the <code>addRepeatingJob</code> API from the lifecycle library.</p>
<p>This example illustrates why <em>structured concurrency is crucial when using coroutines</em> and should always be kept in mind.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The coroutines library went through some growing pains and is still evolving. Even though structured concurrency is the underlying principle of the modern coroutines API, there are still many ways to break it.</p>
<p>Therefore, it is important to be aware of the <em>unstructured concurrency pitfalls</em> so you can avoid them and write better code. Hopefully, this article managed to shine some light on this less-discussed side of the coroutines library.</p>
<p>If you are interested to learn more about how Kotlin coroutines were designed and how structured concurrency came about, I highly recommend watching <a target="_blank" href="https://youtu.be/Mj5P47F6nJg">this presentation</a> from Roman Elizarov.</p>
<p>That said, in Part 4, we will dive deep into error handling in coroutines.</p>
<p>See you then.</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Things every Kotlin Developer should know about Coroutines. Part 2: CoroutineScope.]]></title><description><![CDATA[In my experience, CoroutineScope is one of the less understood parts of the coroutines library, even though it is one of the most important. In Android, we are spoiled with coroutine scopes kindly provided to us by lifecycle libraries, but for many d...]]></description><link>https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-2-coroutinescope</link><guid isPermaLink="true">https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-2-coroutinescope</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Tue, 14 Dec 2021 13:41:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639477245203/xx6LcXZHC.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my experience, <code>CoroutineScope</code> is one of the less understood parts of the coroutines library, even though it is one of the most important. In Android, we are spoiled with coroutine scopes kindly provided to us by lifecycle libraries, but for many developers, things quickly get confusing as soon as there is a need to create a custom <code>CoroutineScope</code>, or if they need to write coroutines in an environment that doesn't provide a pre-defined scope.</p>
<p>That said, by the end of this article, you will know everything you need to use the <code>CoroutineScope</code> comfortably and correctly.</p>
<h2 id="heading-what-is-a-coroutinescope">What is a CoroutineScope</h2>
<h3 id="heading-declaration">Declaration</h3>
<p>First, we have to understand what a <code>CoroutineScope</code> is. There is no better place to look for the answers than its declaration:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CoroutineScope</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">val</span> coroutineContext: CoroutineContext
}
</code></pre>
<p>As you can see, it is <em>a very simple interface</em>, but there is quite a lot to unpack here.</p>
<p>A <code>CoroutineScope</code> is just a simple wrapper for a <code>CoroutineContext</code>. In a technical sense, it is nothing more than a <code>CoroutineContext</code>, and the only reason it exists and has a different name is <em>to differentiate the intended purpose</em> of the two.</p>
<p>You can read more about this in Roman Elizarov's <a target="_blank" href="https://elizarov.medium.com/coroutine-context-and-scope-c8b255d59055">blog post</a> on the topic. I like how in the beginning of his post he gives an example of this concept:</p>
<blockquote>
<p><em>Different uses of physically near-identical things are usually accompanied by giving those things different names to emphasize the intended purpose. Depending on the use, seamen have a dozen or more words for a rope though it might materially be the same thing.</em></p>
</blockquote>
<p>So why do we need to have this separate <code>CoroutineScope</code>?</p>
<h3 id="heading-intended-purpose-of-the-coroutinescope">Intended purpose of the CoroutineScope</h3>
<p>Coroutines <em>are very cheap</em> and we are encouraged to create them as we see fit. We can launch coroutines in different ways from many different places. Some might complete fast, and some might take a long time. Some might have multiple child coroutines of their own. And any of them can potentially fail.</p>
<p>In the early days of the coroutines library, we would <em>launch</em> coroutines in a fire-and-forget manner. However, if we would try to manage all those asynchronously running coroutines in an application that has components with a limited lifecycle, for example, a UI screen that could be closed by the user and should cancel all its work, the complexity of coroutine management would grow exponentially.</p>
<p>Therefore, at one point in its development, the coroutines library had a major ideology shift called <em>Structured Concurrency</em>. It aimed for all coroutines to be launched in a defined scope, which would allow for an easy way to manage cancellation, exception handling and not allow resource leaking.</p>
<p>And that is <em>the intended purpose</em> of a <code>CoroutineScope</code> - <em>to enforce structured concurrency</em>.</p>
<p>We will focus on structured concurrency and how to practically comply with its principles in Part 3 of this series. For now, however, there is still much to discuss about the <code>CoroutineScope</code> itself.</p>
<h3 id="heading-coroutine-launchers">Coroutine launchers</h3>
<p>There are two ways to launch a new coroutine - with either <code>launch</code> or <code>async</code> function. Let's quickly look at their declaration.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> CoroutineScope.<span class="hljs-title">launch</span><span class="hljs-params">(
    context: <span class="hljs-type">CoroutineContext</span> = EmptyCoroutineContext,
    start: <span class="hljs-type">CoroutineStart</span> = CoroutineStart.DEFAULT,
    block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">Unit</span>
)</span></span>: Job
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> CoroutineScope.<span class="hljs-title">async</span><span class="hljs-params">(
    context: <span class="hljs-type">CoroutineContext</span> = EmptyCoroutineContext,
    start: <span class="hljs-type">CoroutineStart</span> = CoroutineStart.DEFAULT,
    block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>
)</span></span>: Deferred&lt;T&gt;
</code></pre>
<p>As much as I would like to dissect every parameter and inner workings of these functions, I will not bore you with that. The main takeaway, which is essential to know and understand, is that these are <em>extension functions</em> on the <code>CoroutineScope</code> interface.</p>
<p>That is why we cannot launch a new coroutine without a scope. </p>
<p>We will return to this concept throughout this article.</p>
<h2 id="heading-creating-your-own-scopes">Creating your own scopes</h2>
<h3 id="heading-scope-builder-functions">Scope builder functions</h3>
<p>There are two types of scope builder functions - suspending and non-suspending. Since we can only call suspending functions from a coroutine, we cannot use them to create our top-level scopes. Still, they are very useful, and we will discuss them later.</p>
<p>To create a top-level scope we can use one of the following builder functions:</p>
<ul>
<li><code>MainScope()</code></li>
<li><code>CoroutineScope(context: CoroutineContext)</code></li>
</ul>
<p>Notice that they are <em>functions</em> - in Kotlin, we often use the pascal case in function names if they build and return an object. That makes for a cleaner and more readable API:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// this is a function that returns an instance</span>
<span class="hljs-comment">// of CoroutineScope, not a constructor</span>
<span class="hljs-keyword">val</span> mainScope = MainScope()
</code></pre>
<p>The main difference between these two scopes is that the <code>MainScope()</code> uses <code>Dispatchers.Main</code> for its coroutines, making it perfect for UI components, and the <code>CoroutineScope()</code> uses <code>Dispatchers.Default</code> by default.</p>
<p>Another difference is that <code>CoroutineScope()</code> takes in a <code>CoroutineContext</code> as a parameter.</p>
<p>If you have read Part 1 of this series, you should be familiar with <code>CoroutineContext</code> and how to use it.</p>
<p>Here are some examples:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> scope1 = CoroutineScope(SupervisorJob())

<span class="hljs-keyword">val</span> scope2 = CoroutineScope(SupervisorJob() + Dispatchers.IO)

<span class="hljs-keyword">val</span> scope3 = CoroutineScope(SupervisorJob() + CoroutineName(<span class="hljs-string">"MyScope"</span>))
</code></pre>
<blockquote>
<p>Note that we are using <code>SupervisorJob</code> instead of <code>Job</code>. It is an important concept regarding error handling, which we will discuss in-depth in Part 4 of this series.</p>
</blockquote>
<p>There are a couple of things to consider when creating a scope using the <code>CoroutineScope()</code> function.</p>
<p>The <code>context</code> parameter is mandatory. That said, if you don't pass a <code>Job</code> element, a default <code>Job()</code> will be created since a scope must have a <code>Job</code> to enforce structured concurrency. Also, if we don't pass a coroutine dispatcher, <code>Dispatchers.Default</code> will be used.</p>
<p>However, given that not every developer knows the inner workings of these functions, I find it convenient and more readable to define the <code>context</code> of my scopes explicitly:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// even though adding Dispatchers.Default is not necessary,</span>
<span class="hljs-comment">// I find it more readable to state every element</span>
<span class="hljs-comment">// of the context explicitly</span>
<span class="hljs-keyword">val</span> appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
</code></pre>
<p>When using the <code>MainScope()</code> function, however, we don't need to specify the context - it automatically creates a context with a <code>SupervisorJob</code> and a <code>Dispatchers.Main</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">MainScope</span><span class="hljs-params">()</span></span>: CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)
</code></pre>
<p>If you need to add an <code>Element</code> to the <code>MainScope</code> you can use the <code>plus</code> operator function, just like we would with a <code>CoroutineContext</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mainScope = MainScope() + CoroutineName(<span class="hljs-string">"MainScope"</span>)
</code></pre>
<h3 id="heading-legacy-convention">Legacy convention</h3>
<p>When <code>CoroutineScope</code> was first introduced into the coroutines library, the official documentation described another way to create scopes. And although the documentation was since updated to recommend a more readable and straightforward way to create scopes as described above, you might still stumble across the legacy way in some codebase.</p>
<p>The legacy way recommended creating coroutine scopes by implementing the <code>CoroutineScope</code> interface:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// standard implementation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyComponent</span> : <span class="hljs-type">CoroutineScope {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> coroutineContext: CoroutineContext = SupervisorJob() + Dispatchers.Default
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-comment">// implementation using delegation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>(), CoroutineScope <span class="hljs-keyword">by</span> MainScope()
</code></pre>
<p>However, you should always use the non-legacy approach in your code, which is more straightforward to use.</p>
<h2 id="heading-suspending-scoped-concurrency">Suspending scoped concurrency</h2>
<h3 id="heading-suspending-scope-builders">Suspending scope builders</h3>
<p>We are not done with scope builder functions just yet. We have looked at non-suspending ways to create coroutine scopes, but as I have mentioned, there are also suspending ones.</p>
<p>There are two, to be exact:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;R&gt;</span> <span class="hljs-title">coroutineScope</span><span class="hljs-params">(block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">R</span>)</span></span>: R
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;R&gt;</span> <span class="hljs-title">supervisorScope</span><span class="hljs-params">(block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">R</span>)</span></span>: R
</code></pre>
<p>There is also a third function that you are already familiar with, which is very similar:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">withContext</span><span class="hljs-params">(
    context: <span class="hljs-type">CoroutineContext</span>,
    block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>
)</span></span>: T
</code></pre>
<p>Although the implementation of <code>withContext()</code> is similar to that of <code>coroutineScope()</code>(but a bit more complicated), its intended purpose is to <em>switch context</em> within a suspending function, not to <em>provide a scope</em>. It might seem confusing, just as with <code>CoroutineScope</code> being the same thing as <code>CoroutineContext</code>, but once again - <em>the intended purpose is the important part</em>.</p>
<p>That said, we will not discuss the <code>withContext()</code> function and focus on the two functions that <em>explicitly provide a scope,</em> even though technically you can do the same things with <code>withContext()</code>, since all these functions take <code>block: suspend CoroutineScope.() -&gt; T</code> as an argument and allow launching new coroutines inside this <code>block</code>.</p>
<p>With that out of the way, let's take a look at a practical example.</p>
<h3 id="heading-why-do-we-need-suspending-scope-builders">Why do we need suspending scope builders</h3>
<p>As you now know, the coroutine launcher functions <code>launch</code> and <code>async</code> are extension functions on the <code>CoroutineScope</code>. We cannot launch new coroutines outside of a coroutine scope. That also means we cannot launch new coroutines from suspending functions since they are regular functions that undergo a "minor" transformation during compilation.</p>
<p>However, there are certainly use cases where we would like to do that.</p>
<p>Here is an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> dataUrls = listOf(<span class="hljs-string">"url1"</span>, <span class="hljs-string">"url2"</span>, <span class="hljs-string">"url3"</span>)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    runBlocking {
        <span class="hljs-keyword">val</span> time = measureTimeMillis {
            downloadAllData(dataUrls)
                .forEach(::println)
        }
        println(<span class="hljs-string">"Done in: <span class="hljs-variable">$time</span> ms"</span>)
    }
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">downloadAllData</span><span class="hljs-params">(urls: <span class="hljs-type">List</span>&lt;<span class="hljs-type">String</span>&gt;)</span></span>: List&lt;Data&gt; {
    <span class="hljs-keyword">return</span> urls.map { url -&gt; downloadData(url) }
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">downloadData</span><span class="hljs-params">(url: <span class="hljs-type">String</span>)</span></span>: Data {
    <span class="hljs-keyword">return</span> withContext(Dispatchers.IO) {
        delay(<span class="hljs-number">100</span>)
        Data(<span class="hljs-string">"I am data from: <span class="hljs-variable">$url</span>"</span>)
    }
}

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Data</span></span>(<span class="hljs-keyword">val</span> content: String)

Output:
Data(content=I am <span class="hljs-keyword">data</span> from: url1)
Data(content=I am <span class="hljs-keyword">data</span> from: url2)
Data(content=I am <span class="hljs-keyword">data</span> from: url3)
Done <span class="hljs-keyword">in</span>: <span class="hljs-number">329</span> ms
</code></pre>
<p>Predictably, we got our data downloaded sequentially in about <code>300ms</code>. Of course, we could add <code>async</code> to each call of <code>downloadData</code> in our top-level coroutine, but that would be detrimental to the quality and reusability of our code. We can do better than that.</p>
<p>With the help of suspending scope builders, we can load all our data concurrently inside the <code>downloadAllData</code> function:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">downloadAllData</span><span class="hljs-params">(urls: <span class="hljs-type">List</span>&lt;<span class="hljs-type">String</span>&gt;)</span></span>: List&lt;Data&gt; {
    <span class="hljs-keyword">return</span> coroutineScope {
        urls.map { url -&gt; async { downloadData(url) } }
            .map { deferred -&gt; deferred.await() }
    }
}

Output:
Data(content=I am <span class="hljs-keyword">data</span> from: url1)
Data(content=I am <span class="hljs-keyword">data</span> from: url2)
Data(content=I am <span class="hljs-keyword">data</span> from: url3)
Done <span class="hljs-keyword">in</span>: <span class="hljs-number">129</span> ms
</code></pre>
<p>An important thing to note about suspending scope builders is that they <em>return only when all their child coroutines have finished</em>. This <em>enforces structured concurrency</em> and adheres to one of the main ideologies of the coroutine library - that suspending functions <em>execute sequentially</em>, just like the regular code. So in the example above, even though we launch multiple new coroutines inside the <code>downloadAllData</code> function, it will only return when all the work is done, without leaking coroutines. We will talk more about it in the best practices section.</p>
<p>The <code>supervisorScope()</code> is the same as <code>coroutineScope()</code>, but uses a <code>SupervisorJob</code> for its context instead of a <code>Job</code>. We will discuss everything there is to know about using <code>Job</code> and <code>SupervisorJob</code> in Part 4 of this series dedicated to error handling.</p>
<h2 id="heading-a-few-words-about-globalscope">A few words about GlobalScope</h2>
<p>This article would not be complete if we didn't mention the infamous <code>GlobalScope</code>. It had confused so many developers that in Kotlin 1.5 JetBrains marked it with <code>@DelicateCoroutinesApi</code>, which requires an opt-in to use it.</p>
<p>There are a couple of things you need to know about the <code>GlobalScope</code>, which should be easier to understand now that you know how scopes work and why we need them.</p>
<p>First of all, the <code>GlobalScope</code> <em>doesn't adhere to the structured concurrency principle</em>, which, as you now know, is a big deal in coroutines. It doesn't have any <code>Job</code> tied to it, and it is running during the whole lifetime of an application.</p>
<p>It might have its uses, but to use the <code>GlobalScope</code> correctly, you have to manage every coroutine launched inside it manually, keeping track of their jobs and not forgetting to <code>.join()</code> those jobs to other coroutines if your use case requires it.</p>
<p>You have to know what you are doing when using the <code>GlobalScope</code>, and even then, you might still introduce some subtle bugs if your attention slips.</p>
<p>So the recommendation is to <em>avoid it altogether</em>.</p>
<p>You can read more about this topic in <a target="_blank" href="https://elizarov.medium.com/the-reason-to-avoid-globalscope-835337445abc">this post</a> by Roman Elizarov.</p>
<h2 id="heading-conventions-and-best-practices">Conventions and Best Practices</h2>
<p>We have already discussed quite a few examples of using the <code>CoroutineScope</code> correctly. However, there are still some things that you should keep in mind.</p>
<p>First of all, as we have mentioned earlier - do not ever launch new unbounded coroutines from a suspending function. Nothing should be left running in the background when a suspending function returns.</p>
<p>You should never write code like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">launchWorker</span><span class="hljs-params">()</span></span> {
    ... <span class="hljs-comment">// any suspending code</span>
    CoroutineScope(Dispatchers.IO).launch { 
        doWork()
    }
}
</code></pre>
<p>Even if you keep a job handle to this new coroutine - this implementation is very smelly. It will make your code unpredictable, and you will break the structured concurrency principle.</p>
<p>If you need to write a function that launches a new coroutine, the convention is to use <em>a regular extension function</em> on the <code>CoroutineScope</code> - just like the <code>launch</code> and <code>async</code> functions.</p>
<p>The correct way to implement the example above would be:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> CoroutineScope.<span class="hljs-title">launchWorker</span><span class="hljs-params">()</span></span> {
    launch {
        <span class="hljs-comment">// switch the dispatcher inside doWork() if needed</span>
        <span class="hljs-comment">// as we have discussed in Part 1</span>
        doWork()
    }
}
</code></pre>
<p>Now you can launch your custom coroutines safely inside the context of a scope.</p>
<p>This convention also follows the pattern that <em>launching a new coroutine returns immediately</em> while <em>suspending functions return only after all the work is completed</em>.</p>
<p>Another best practice for creating your own <code>CoroutineScope</code> is to keep it bound to the lifecycle of some component. For example, in Android, we have <code>viewModelScope</code> attached to the <code>ViewModel</code>, and <code>lifecycleScope</code> attached to the <code>LifecycleOwner</code>. As soon as these components are destroyed, their scopes are immediately cancelled, preventing leaking coroutines.</p>
<p>This is a good practice regardless of the platform. You might have an application-level <code>CoroutineScope</code>, which might not need explicit cancelling, but for any other use case, you should limit the lifecycle of your scopes:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyComponent</span></span>() {
    <span class="hljs-keyword">val</span> scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
    ...
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">()</span></span> {
        ...
        scope.cancel()
    }
}
</code></pre>
<p>Lastly, it is more clean and readable to use extension properties and functions like <code>isActive</code>, <code>cancel()</code>, and <code>ensureActive()</code> on your <code>CoroutineScope</code> not on the <code>CoroutineContext</code> even though they are the same thing. "Cancelling a scope" is immediately apparent, while "cancelling a context" occasionally might raise some questions just because of the naming.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You might have noticed a trend that despite having a very flexible API, the coroutines library has a set of simple, straightforward recommendations and practices, which make using coroutines much less intimidating, especially when starting out.</p>
<p>Hopefully, after reading this article, using the <code>CoroutineScope</code> will be smooth sailing.</p>
<p>In Part 3, we will dive deeper into the practical side of structured concurrency. This more advanced subject will nicely round up our discussion about <code>CoroutineContext</code> and <code>CoroutineScope</code> before moving on to meatier topics like exception handling.</p>
<p>See you next time.</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Things every Kotlin Developer should know about Coroutines. 

Part 1: CoroutineContext.]]></title><description><![CDATA[The CoroutineContext is the backbone of the coroutines library. Every coroutine you launch will have a context. However, given its nature and flexible API, it might prove pretty tricky to use it correctly.
In Part 1 of my series about coroutines, I w...]]></description><link>https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-1-coroutinecontext</link><guid isPermaLink="true">https://maxkim.dev/things-every-kotlin-developer-should-know-about-coroutines-part-1-coroutinecontext</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[coroutines]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Thu, 02 Dec 2021 08:24:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638386151096/lme5o9O7D.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>CoroutineContext</code> is the backbone of the coroutines library. Every coroutine you launch will have a context. However, given its nature and flexible API, it might prove pretty tricky to use it correctly.</p>
<p>In Part 1 of my series about coroutines, I will take a close look at the <code>CoroutineContext</code> and discuss the best practices on how to use it.</p>
<h2 id="heading-coroutinecontext-under-the-hood">CoroutineContext Under the Hood</h2>
<p>To kick this article off, let's take a look at the declaration of <code>CoroutineContext</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Persistent context for the coroutine. 
 * It is an indexed set of [Element] instances.
 * An indexed set is a mix between a set and a map.
 * Every element in this set has a unique [Key].
 */</span>
<span class="hljs-meta">@SinceKotlin(<span class="hljs-meta-string">"1.3"</span>)</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CoroutineContext</span></span>
</code></pre>
<p>As we can see from the KDoc, in broad terms, the <code>CoroutineContext</code> is just a <code>Map</code> that stores a set of <code>Element</code> objects that have a unique <code>Key</code>.</p>
<p>We can access those <code>Element</code>s using a <code>Key</code>, just as we would in a normal <code>Map</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
  * Returns the element with the given [key] from this context or `null`.
  */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;E : Element&gt;</span> <span class="hljs-title">get</span><span class="hljs-params">(key: <span class="hljs-type">Key</span>&lt;<span class="hljs-type">E</span>&gt;)</span></span>: E?
</code></pre>
<p>However, notice that the <code>Key</code> is typed. We will discuss that a bit later.</p>
<h2 id="heading-coroutinecontext-elements">CoroutineContext Elements</h2>
<p>Since <code>CoroutineContext</code> is nothing more than a container, the most important part is its content.</p>
<p>An <code>Element</code> is anything a coroutine might need to run correctly. The most common examples would be:</p>
<ul>
<li><code>Job</code> - a cancellable handle to a coroutine with a lifecycle;</li>
<li><code>CoroutineDispatcher</code>, <code>MainCoroutineDispatcher</code> - dispatchers for a coroutine to run on;</li>
<li><code>CoroutineId</code>, <code>CoroutineName</code>  - elements mainly used to debug coroutines;</li>
<li><code>CoroutineExceptionHandler</code> - an element that handles uncaught exceptions.</li>
</ul>
<p>There are many more elements defined in the coroutines library, but these are the main ones that you would use in your code.</p>
<p>When it comes to the implementation of <code>Element</code>s, it is curious how the coroutines library uses typed <code>Key</code>s.</p>
<p>Here is how we would get a <code>Job</code> from the coroutine context, using a <code>Key</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> job = coroutineContext[Job]
</code></pre>
<p>As you can see, the <code>Key</code> is just the name of the <code>Element</code> we want to access. This is not a syntax you see often, but it is a perfectly valid Kotlin syntax nevertheless.</p>
<p>The <code>Key</code> for each <code>Element</code> is just a plain <code>companion object</code> of that element that implements <code>Key&lt;Element&gt;</code> interface, and therefore, we can use it as a <code>Key</code> for the given type.</p>
<p>Here is an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Job</span> : <span class="hljs-type">CoroutineContext.Element {</span></span>
    <span class="hljs-comment">/**
     * Key for [Job] instance in the coroutine context.
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> Key : CoroutineContext.Key&lt;Job&gt;
</code></pre>
<h2 id="heading-modifying-a-coroutinecontext">Modifying a CoroutineContext</h2>
<p>A <code>CoroutineContext</code> behaves like an immutable map - it doesn't have a <code>set</code> function. Therefore, you can read stored elements, but can't modify them directly:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// we can read the elements stored in a context by their Key</span>
<span class="hljs-keyword">val</span> job = coroutineContext[Job] 
<span class="hljs-comment">// we cannot modify stored elements</span>
coroutineContext[Job] = Job() &lt;- compiler error
</code></pre>
<p>That doesn't mean, however, that we cannot modify a <code>CoroutineContext</code>. For that, it has dedicated functions, such as:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
  * Returns a context containing elements from this context 
  * and elements from  other [context].
  * The elements from this context with the same key 
  * as in the other one are dropped.
  */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">plus</span><span class="hljs-params">(context: <span class="hljs-type">CoroutineContext</span>)</span></span>: CoroutineContext
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
  * Returns a context containing elements from this context, 
  * but without an element with the specified [key].
  */</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">minusKey</span><span class="hljs-params">(key: <span class="hljs-type">Key</span>&lt;*&gt;)</span></span>: CoroutineContext
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Accumulates entries of this context starting with[initial] value
 * and applying[operation] from left to right to current accumulator value 
 * and each element of this context.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fun</span><span class="hljs-type">&lt;R&gt;</span><span class="hljs-title">fold</span><span class="hljs-params">(initial: <span class="hljs-type">R</span>, operation:(<span class="hljs-type">R</span>, <span class="hljs-type">Element</span>)-&gt; <span class="hljs-type">R</span>)</span></span>: R
</code></pre>
<p>Out of the functions mentioned above, in most cases, you would only use the <code>plus</code> operator function, which uses the <code>fold</code> function under the hood.</p>
<p>If you have used coroutines before, the <code>plus</code> operator should be very familiar to you:</p>
<pre><code class="lang-kotlin">launch(Dispatchers.IO + CoroutineName(<span class="hljs-string">"TestCoroutine"</span>)) {
    doStuff()
}
</code></pre>
<p>Keep in mind that this <code>plus</code> is <em>not associative</em>. In other words, <code>context1</code> + <code>context2</code> is not the same as <code>context2</code> + <code>context1</code> since all the keys from the left context will be overwritten by the keys from the right context. Of course, It doesn't matter when combining two distinct <code>Element</code>s as in the example above, but when combining sets of <code>Element</code>s, this becomes an important consideration.</p>
<p>And yes, this example also means that every <code>Element</code> is also a <code>CoroutineContext</code> to allow for such a syntax:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * An element of the [CoroutineContext]. An element 
 * of the coroutine context is a singleton context by itself.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Element</span> : <span class="hljs-type">CoroutineContext</span></span>
</code></pre>
<p>Each <code>Element</code> by itself is a valid <code>CoroutineContext</code> that can be combined with other <code>Element</code>s and/or <code>CoroutineContext</code>s.</p>
<p>This also means that we can use the <code>get</code> syntax on any <code>Element</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// nonsense, but api allows it</span>
<span class="hljs-keyword">val</span> job = Job()[Job]
</code></pre>
<p>That is not something that you would ever use in your code. Still, I find this example somewhat educational to illustrate the point above and the flexibility of coroutines API.</p>
<p>The rest of the <code>CoroutineContext</code>'s public API is realized with the help of extension functions and properties that access some functionality of an <code>Element</code>.</p>
<p>Here is an example of a property that checks whether or not a <code>CoroutineContext</code> is active:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">val</span> CoroutineContext.isActive: <span class="hljs-built_in">Boolean</span>
    <span class="hljs-keyword">get</span>() = <span class="hljs-keyword">this</span>[Job]?.isActive == <span class="hljs-literal">true</span>
</code></pre>
<p>We will not focus on these extensions for now, since in most cases, it would make sense to use similar functions on a <code>CoroutineScope</code>, but we will talk about it in Part 2 of this series.</p>
<h2 id="heading-best-practices-and-recommendations">Best Practices and Recommendations</h2>
<p>As you have seen, the <code>CoroutineContext</code> API is very flexible and allows us to add and combine different elements as we see fit.</p>
<p>However, <em>you should almost never do that</em>.</p>
<p>These flexible APIs are one of the reasons for the steep learning curve of the coroutines library. The thing is that <em>most of that flexibility is not meant for the end-user</em>. We will discuss why it is this way in one of the later parts of this series.</p>
<p>It is very easy to mess things up, especially when starting out using coroutines. So, to make things a bit easier, here are some recommendations on using the <code>CoroutineContext</code>.</p>
<p>First of all, the only elements you should ever consider manually adding to the context when launching a new coroutine are <code>CoroutineDispather</code> (or <code>MainCoroutineDispatcher</code>) and <code>CoroutineExceptionHandler</code>. In some specific debug cases, you can also use <code>CoroutineName</code>.</p>
<p>Here is an example of changing a dispatcher: </p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    runBlocking {
        println(<span class="hljs-string">"I am running on <span class="hljs-subst">${Thread.currentThread().name}</span>"</span>)
        launch(Dispatchers.IO) {
            workOnIO() <span class="hljs-comment">// this might be blocking</span>
        }
    }
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">workOnIO</span><span class="hljs-params">()</span></span> {
    delay(<span class="hljs-number">100</span>)
    println(<span class="hljs-string">"Now I have switched to <span class="hljs-subst">${Thread.currentThread().name}</span>"</span>)
}

Output:
I am running on main
Now I have switched to DefaultDispatcher-worker-<span class="hljs-number">1</span>
</code></pre>
<blockquote>
<p><strong><em>Important!</em></strong> <code>runBlocking</code> should never be used outside tests and examples like these. In production code, coroutines must have a proper scope. I am using it in this article for illustrational purposes only.</p>
</blockquote>
<p>One thing to keep in mind here is that <code>Dispatchers.IO</code> shares threads with <code>Dispatchers.Default</code>. Therefore we get this output.</p>
<p>Also notice that when we manage our dispatchers from the top-level coroutine, we might launch a suspending function that will block our thread. For example, if the <code>workOnIO</code> function instead of the non-blocking <code>delay()</code> called <code>Thread.sleep()</code>, or, more realistically, read from a huge file.</p>
<p>A coroutine will wait for a suspending function to finish regardless since <em>the execution of suspending functions is sequential</em>, but if we don't block the thread while waiting for a coroutine to resume, it is free to do other work.</p>
<p>With that in mind, there is one recommendation about dispatchers that <a target="_blank" href="https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761">comes from Kotlin's project lead Roman Elizarov</a>, who was the lead designer of coroutines library before that.</p>
<p>Here is an important excerpt:</p>
<blockquote>
<p>Suspending functions add a new dimension to code design. It was blocking/non-blocking without coroutines and now there is also suspending/non-suspending on top of that. To make everybody’s life simpler we use the following <em>convention</em>: <strong>suspending functions do not block the caller thread</strong>. The means to implement this convention are provided by the <code>withContext</code> function.</p>
</blockquote>
<p>With that convention in mind, here is how we could improve that code:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    runBlocking {
        launch {
            println(<span class="hljs-string">"I am running on <span class="hljs-subst">${Thread.currentThread().name}</span>"</span>)
            workOnIO()
        }
    }
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">workOnIO</span><span class="hljs-params">()</span></span> {
    withContext(Dispatchers.IO) {
        delay(<span class="hljs-number">100</span>)
        println(<span class="hljs-string">"Now I have switched to <span class="hljs-subst">${Thread.currentThread().name}</span>"</span>)
    }
}

Output:
I am running on main
Now I have switched to DefaultDispatcher-worker-<span class="hljs-number">1</span>
</code></pre>
<p>Function <code>workOnIO</code> might still block a thread, but not the thread we are calling it from. Also, by following this convention, you won't have to check every time what happens inside a suspending function and whether you need to switch threads for it.</p>
<p>When it comes to <code>CoroutineExceptionHandler</code>, we will talk about it in more detail when we get to exception handling in coroutines. For now, here is a simple example:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> scope = CoroutineScope(Dispatchers.Default)
    <span class="hljs-keyword">val</span> exceptionHandler = CoroutineExceptionHandler { _, throwable -&gt;
        println(<span class="hljs-string">"I have caught: <span class="hljs-subst">${throwable.message}</span>"</span>)
    }

    runBlocking {
        scope.launch(exceptionHandler) {
            println(<span class="hljs-string">"I am running!"</span>)
            delay(<span class="hljs-number">100</span>)
            error(<span class="hljs-string">"A nasty exception!"</span>)
        }

        delay(<span class="hljs-number">200</span>)
        println(<span class="hljs-string">"I am OK!"</span>)
    }
}

Output:
I am running!
I have caught: A nasty exception!
I am OK!
</code></pre>
<p>Lastly, sometimes it might prove handy to identify your coroutines for debug purposes. You can do it using <code>CoroutineName</code> element:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    runBlocking {
        launch(CoroutineName(<span class="hljs-string">"A"</span>)) {
            identify()
        }

        launch(CoroutineName(<span class="hljs-string">"B"</span>)) {
            identify()
        }
    }
}

<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">identify</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> coroutineName = coroutineContext[CoroutineName]?.name
    println(<span class="hljs-string">"I am called from: <span class="hljs-variable">$coroutineName</span>"</span>)
}

Output:
I am called from: A
I am called from: B
</code></pre>
<p>You can also use the <code>-Dkotlinx.coroutines.debug</code> JVM option to see the specified coroutine name in the logs.</p>
<p>You should rarely modify a <code>CoroutineContext</code> outside of these use cases unless you know what you are doing. Otherwise, it might break things you are not even aware of and result in hard-to-find bugs. Especially when introducing a new <code>Job</code> into the context - a topic we will discuss in a later article.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you stick to these recommendations, you won't have much trouble using the <code>CoroutineContext</code>. I could have just given you those and called it an article, but I believe it is crucial to understand the inner workings of the tools we use.</p>
<p>Next time, we will look into the <code>CoroutineScope</code>, which has more in common with the <code>CoroutineContext</code> than you might think.</p>
<p>See you next time,</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[A Practical Guide to Kotlin's inline Modifier]]></title><description><![CDATA[I fell in love with Kotlin as soon as I switched to it from Java about 4 years ago. And although I was writing Kotlin code on a regular basis ever since, I didn't start using some of its more advanced features until quite recently.
I wish I had start...]]></description><link>https://maxkim.dev/a-practical-guide-to-kotlins-inline-modifier</link><guid isPermaLink="true">https://maxkim.dev/a-practical-guide-to-kotlins-inline-modifier</guid><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Mon, 04 Oct 2021 08:48:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633257088662/baRNBzc2X.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I fell in love with Kotlin as soon as I switched to it from Java about 4 years ago. And although I was writing Kotlin code on a regular basis ever since, I didn't start using some of its more advanced features until quite recently.</p>
<p>I wish I had started playing around with the more idiomatic ways to write Kotlin code much sooner since it improves the quality of the code and makes writing code much more enjoyable. I agree that you can easily get by without ever using the less-known Kotlin features, however, in the hands of more dedicated software enthusiasts, those features can help improve the code dramatically.</p>
<p>In this article, we will go through one of those features - the <code>inline</code> modifier. And yes, it means we will also take a close look at the modifiers that are closely linked with the inline functions - <code>noinline</code>, <code>crossinline</code>, and <code>reified</code>.</p>
<h2 id="contents">Contents</h2>
<pre><code><span class="hljs-number">1</span><span class="hljs-string">.</span> <span class="hljs-string">Inline</span> <span class="hljs-string">modifier</span>
   <span class="hljs-number">1.1</span><span class="hljs-string">.</span> <span class="hljs-string">Inline</span> <span class="hljs-string">functions</span>
   <span class="hljs-number">1.2</span><span class="hljs-string">.</span> <span class="hljs-string">Inline</span> <span class="hljs-string">properties</span>
   <span class="hljs-number">1.3</span><span class="hljs-string">.</span> <span class="hljs-string">Inline</span> <span class="hljs-string">classes</span>
<span class="hljs-number">2</span><span class="hljs-string">.</span> <span class="hljs-string">Noinline</span> <span class="hljs-string">modifier</span>
<span class="hljs-number">3</span><span class="hljs-string">.</span> <span class="hljs-string">Crossinline</span> <span class="hljs-string">modifier</span>
   <span class="hljs-number">3.1</span><span class="hljs-string">.</span> <span class="hljs-string">Understanding</span> <span class="hljs-string">non-local</span> <span class="hljs-string">returns</span>
   <span class="hljs-number">3.2</span><span class="hljs-string">.</span> <span class="hljs-string">The</span> <span class="hljs-string">problem</span> <span class="hljs-string">and</span> <span class="hljs-string">the</span> <span class="hljs-string">crossinline</span> <span class="hljs-string">solution</span>
<span class="hljs-number">4</span><span class="hljs-string">.</span> <span class="hljs-string">Reified</span> <span class="hljs-string">modifier</span>
</code></pre><h2 id="1-inline-modifier">1. Inline modifier</h2>
<h3 id="11-inline-functions">1.1. Inline functions</h3>
<p>In Kotlin, you cannot throw a stone without hitting a <em>higher-order function</em>. In layman's terms, those are functions that either take functions as parameters or return a function. This makes Kotlin a very flexible language and allows for intuitive functional programming as well as easy creation of DSLs among many other things.</p>
<p>But as with most amazing things in life, there is a catch. Using many higher-order functions can cause a significant performance impact during runtime since every function <em>compiles to an object that captures a closure</em>. A closure is a fancy way of describing the variables that this function accesses but are declared outside of its scope. Therefore, without a clever solution from the folk at JetBrains, Kotlin might as well have been called the runtime overhead language.</p>
<p>That solution is the <code>inline</code> modifier.</p>
<p>When a function is marked with <code>inline</code> the compiler <em>doesn't create new objects but rather inserts the given code where an inline function is called</em>.</p>
<p>Let's take a look at a simple example:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    doubleAction(
        { println(<span class="hljs-string">"Hello"</span>) },
        { println(<span class="hljs-string">"World!"</span>) }
    )
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doubleAction</span><span class="hljs-params">(
    action1: () -&gt; <span class="hljs-type">Unit</span>,
    action2: () -&gt; <span class="hljs-type">Unit</span>
)</span></span> {
    action1()
    action2()
}
</code></pre>
<p>If we decompile the bytecode of this block back to Java and look at the <code>main()</code> function, we will see:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    doubleAction((Function0)<span class="hljs-keyword">null</span>.INSTANCE, (Function0)<span class="hljs-keyword">null</span>.INSTANCE);
}
</code></pre>
<p>To be honest, at first glance this looks like someone is looking for a creative way to get a <code>NullPointerException</code> but let's not concern ourselves with the ways of Kotlin bytecode decompiler.</p>
<p>What we should note here is that our <code>main</code> is calling the <code>doubleAction</code> function and our two lambdas are now instances of <code>Function0</code> object.</p>
<p>Now, let's see what happens if we put the <code>inline</code> modifier in front of the <code>doubleAction</code> function:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doubleAction</span><span class="hljs-params">(
    action1: () -&gt; <span class="hljs-type">Unit</span>,
    action2: () -&gt; <span class="hljs-type">Unit</span>
)</span></span> {
    action1()
    action2()
}
</code></pre>
<p>Just by doing that, after compiling this code into bytecode and decompiling back to Java (and a little bit of cleanup to illustrate the point) the body of our <code>main</code> function reads:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    String var1 = <span class="hljs-string">"Hello"</span>;
    System.out.println(var1);
    var1 = <span class="hljs-string">"World!"</span>;
    System.out.println(var1);
}
</code></pre>
<p>Now that is much more efficient! The compiler even reuses the <code>String</code> variable.</p>
<p>I hope that this example nicely illustrates the benefits of using the <code>inline</code> modifier for higher-order functions. <em>It will inline the function itself as well as lambdas that are passed as arguments.</em></p>
<p><strong>In summary</strong></p>
<p>The <code>inline</code> modifier provides a noticeable performance boost if you write a lot of higher-order functions, especially in a big codebase, so use it!</p>
<p>Also, for those of you writing Android UI with Jetpack Compose, <code>inline</code> will become your friend pretty fast.</p>
<p>However, a word of caution must be mentioned here. It is not recommended to <code>inline</code> <em>large functions</em>, since it can considerably bloat the generated code. Inlining, like everything else really, is good in moderation.</p>
<p>It works great with short functions, especially when using loops and working with collections.</p>
<p>For example, in Kotlin standard library the scope functions (<code>let</code>, <code>apply</code>, <code>also</code>, <code>run</code>, and <code>with</code>) are marked with <code>inline</code>, as well as extension functions that work with <code>Iterable</code> collections, such as <code>map</code>, <code>forEach</code>, <code>fold</code> and many others.</p>
<h3 id="12-inline-properties">1.2. Inline properties</h3>
<p>Marking higher-order functions is not the only use of the <code>inline</code> modifier, however. One of the less-known features of the Kotlin language are <strong>inline properties</strong>.</p>
<p>Let's take a look at the following example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> complexProperty: <span class="hljs-built_in">Int</span>
    <span class="hljs-keyword">get</span>() {
        <span class="hljs-keyword">val</span> x = <span class="hljs-number">2</span>
        <span class="hljs-keyword">val</span> y = <span class="hljs-number">4</span>
        <span class="hljs-keyword">return</span> x + y
    }
    <span class="hljs-keyword">set</span>(value) {
        <span class="hljs-keyword">val</span> adjustedValue = value + <span class="hljs-number">10</span>
        println(<span class="hljs-string">"Setting adjusted value <span class="hljs-variable">$adjustedValue</span>"</span>)
    }

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    complexProperty = <span class="hljs-number">4</span>
    <span class="hljs-keyword">val</span> calculatedProperty = complexProperty
    println(<span class="hljs-string">"The property is <span class="hljs-variable">$calculatedProperty</span>"</span>)
}
</code></pre>
<blockquote>
<p>Take note that these are not regular getter and setter methods that read/write a backing field. We will discuss it in a bit.</p>
</blockquote>
<p>The accessors of Kotlin properties are compiled to regular methods, which then are used throughout the code. So our example after the bytecode magic will read:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    setComplexProperty(<span class="hljs-number">4</span>);
    <span class="hljs-keyword">int</span> calculatedProperty = getComplexProperty();
    String var1 = <span class="hljs-string">"The property is "</span> + calculatedProperty;
    System.out.println(var1);
}
</code></pre>
<p>If you have paid attention until now, you probably know what we are about to do.</p>
<p>Yes, we can mark the property as <code>inline</code>, which will make the accessors of the property work like regular inline functions, <strong>even though they are not higher-order</strong>. </p>
<p>So after marking our property with <code>inline</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-keyword">var</span> complexProperty: <span class="hljs-built_in">Int</span>
    <span class="hljs-keyword">get</span>() {
        <span class="hljs-keyword">val</span> x = <span class="hljs-number">2</span>
        <span class="hljs-keyword">val</span> y = <span class="hljs-number">4</span>
        <span class="hljs-keyword">return</span> x + y
    }
    <span class="hljs-keyword">set</span>(value) {
        <span class="hljs-keyword">val</span> adjustedValue = value + <span class="hljs-number">10</span>
        println(<span class="hljs-string">"Setting adjusted value <span class="hljs-variable">$adjustedValue</span>"</span>)
    }
</code></pre>
<p>We will get:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-comment">// Setter</span>
    <span class="hljs-keyword">int</span> value$iv = <span class="hljs-number">4</span>;
    <span class="hljs-keyword">int</span> adjustedValue$iv = value$iv + <span class="hljs-number">10</span>;
    String var3 = <span class="hljs-string">"Setting adjusted value "</span> + adjustedValue$iv;
    System.out.println(var3);

    <span class="hljs-comment">// Getter</span>
    <span class="hljs-keyword">int</span> x$iv = <span class="hljs-number">2</span>;
    <span class="hljs-keyword">int</span> y$iv = <span class="hljs-number">4</span>;
    <span class="hljs-keyword">int</span> calculatedProperty = x$iv + y$iv;
    String var6 = <span class="hljs-string">"The property is "</span> + calculatedProperty;
    System.out.println(var6);
}
</code></pre>
<p>Exactly what we would expect from an inlined function.</p>
<p>We can also mark individual accessors as <code>inline</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> complexProperty: <span class="hljs-built_in">Int</span>
    <span class="hljs-keyword">inline</span> <span class="hljs-keyword">get</span>() {
        ...
    }
    <span class="hljs-keyword">set</span>(value) {
        ...
    }
</code></pre>
<p>Or:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> complexProperty: <span class="hljs-built_in">Int</span>
    <span class="hljs-keyword">get</span>() {
        ...
    }
    <span class="hljs-keyword">inline</span> <span class="hljs-keyword">set</span>(value) {
        ...
    }
</code></pre>
<p>And of course, have read-only properties:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-keyword">val</span> complexProperty: <span class="hljs-built_in">Int</span>
    <span class="hljs-keyword">get</span>() {
       ...
    }
</code></pre>
<p><strong>Inline property restriction</strong></p>
<p>There is a reason why we didn't use a property with regular getter and setter in our example. That reason is that the <code>inline</code> modifier is only allowed for accessors that don't have a backing field.</p>
<blockquote>
<p>Backing field is an identifier <strong>field</strong> that doesn't allow us to go into an infinite loop when setting a property.</p>
</blockquote>
<h3 id="13-inline-classes">1.3. Inline classes</h3>
<p>Inline classes are another less-known feature of Kotlin that became stable in Kotlin 1.5.0, and even though they are not using the <code>inline</code> modifier directly in their stable version, they did during the experimental phase in earlier Koltin versions, and their functionality is the same as we have seen with previous inlined examples.</p>
<p>Inline classes act as a wrapper around a type <em>to improve readability and decrease the probability of runtime bugs</em>. The regular wrapper class would have a noticeable performance hit during runtime due to additional heap allocations. The inline classes don't, while keeping all the benefits.</p>
<p>Below is a snippet of code where we should consider using a wrapper:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    login(<span class="hljs-string">"qwerty"</span>, <span class="hljs-string">"email@qwerty.com"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">login</span><span class="hljs-params">(email: <span class="hljs-type">String</span>, password: <span class="hljs-type">String</span>)</span></span> {
    println(<span class="hljs-string">"Please don't mix up my parameters"</span>)
}
</code></pre>
<p>As you can see, this code will compile nicely but would break during runtime (if it had some login logic of course).</p>
<p>This is where inline classes shine.</p>
<p>We can re-write the following code as follows:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    login(Email(<span class="hljs-string">"email@qwerty.com"</span>), Password(<span class="hljs-string">"qwerty"</span>))
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">login</span><span class="hljs-params">(email: <span class="hljs-type">Email</span>, password: <span class="hljs-type">Password</span>)</span></span> {
    println(<span class="hljs-string">"Please don't mix up my parameters"</span>)
}

<span class="hljs-meta">@JvmInline</span>
value <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Email</span></span>(<span class="hljs-keyword">val</span> email: String)

<span class="hljs-meta">@JvmInline</span>
value <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Password</span></span>(<span class="hljs-keyword">val</span> password: String)
</code></pre>
<p>Before Kotlin 1.5.0 we would write:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Email</span></span>(<span class="hljs-keyword">val</span> email: String)
</code></pre>
<p>But this syntax is deprecated now and will throw a warning.</p>
<p>When using this approach it will be much harder to mix up our types, and during runtime no new objects will be created.</p>
<p>Moreover, the inline classes can have <code>init</code> blocks, functions, and properties (with the same restrictions as the inline properties):</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@JvmInline</span>
value <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Email</span></span>(<span class="hljs-keyword">val</span> email: String) {
    <span class="hljs-keyword">init</span> {
        require(email.isValidEmail())
    }
}

<span class="hljs-meta">@JvmInline</span>
value <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Password</span></span>(<span class="hljs-keyword">val</span> password: String) {
    <span class="hljs-keyword">val</span> isSecure: <span class="hljs-built_in">Boolean</span>
        <span class="hljs-keyword">get</span>() = password.contains(<span class="hljs-string">'!'</span>)
}
</code></pre>
<p>If you want some more practical inspiration on the inline classes, you can take a look at this <a target="_blank" href="https://jakewharton.com/inline-classes-make-great-database-ids/">article</a> by Jake Wharton.</p>
<h2 id="2-noinline-modifier">2. Noinline modifier</h2>
<p>At this point, we hopefully have a decent understanding of how inlining works, therefore let's take a look at the modifiers that work in the context of inline functions.</p>
<p>The first of those modifiers is quite straightforward.</p>
<p>If we don't want to (or can't) inline a lambda that is passed as a parameter to an inline function, we can mark it as <code>noinline</code>.</p>
<p>Here are a couple examples where we might wan't to mark our lambda parameter as <code>noinline</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doubleAction</span><span class="hljs-params">(
    action1: () -&gt; <span class="hljs-type">Unit</span>,
    action2: () -&gt; <span class="hljs-type">Unit</span>
)</span></span> {
    action1()

    <span class="hljs-comment">// the following two cases won't compile</span>
    <span class="hljs-comment">// we cannot assign an inline lambda to a variable</span>
    <span class="hljs-keyword">val</span> x = action2
    <span class="hljs-comment">// we cannot pass an inline lambda to a non-inline function</span>
    singleAction(action2)
}

<span class="hljs-comment">/**
 * For some reason this function is not inlined.
 * It might be too large or comes from external
 * library that we don't have any control over
 */</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">singleAction</span><span class="hljs-params">(action: () -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    action()
}
</code></pre>
<p>This can easily be fixed by telling the compiler that we don't want to inline the <code>action2</code> lambda. All we need to do is mark it as <code>noinline</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doubleAction</span><span class="hljs-params">(
    action1: () -&gt; <span class="hljs-type">Unit</span>,
    <span class="hljs-keyword">noinline</span> action2: () -&gt; <span class="hljs-type">Unit</span>
)</span></span> {
    ...
}
</code></pre>
<p>Now the above code will compile and work nicely.</p>
<p>Needless to say that if you have and inline function with one lambda as a parameter, in most cases it wouldn't make sense to mark in as <code>noinline</code>, and the IDE will promptly give you warning in that case.</p>
<p>However, it depends on what we do with that lambda parameter.</p>
<p>Here is an example from the Kotlin Coroutines library:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> CoroutineDispatcher.<span class="hljs-title">invoke</span><span class="hljs-params">(
    <span class="hljs-keyword">noinline</span> block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>
)</span></span>: T = withContext(<span class="hljs-keyword">this</span>, block)
</code></pre>
<p>The <code>withContext</code> is a regular function and we cannot pass an inlined lambda to it (more on why in the <code>crossinline</code> section):</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">public</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">withContext</span><span class="hljs-params">(
    context: <span class="hljs-type">CoroutineContext</span>,
    block: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>
)</span></span>: T
</code></pre>
<p>But we can still inline the <code>withContext</code> function where we call <code>invoke</code> on our <code>CoroutineScope</code> so this is another good example of <code>noinline</code> modifier in practice.</p>
<h2 id="3-crossinline-modifier">3. Crossinline modifier</h2>
<p>To understand why we might need the <code>crossinline</code> modifier, we must first have a good understanding of <strong>non-local returns</strong> in Kotlin.</p>
<p>If you are familiar with this concept, feel free to skip the next part.</p>
<h3 id="31-understanding-non-local-returns">3.1. Understanding non-local returns</h3>
<p>There are only 3 places in Kotlin where we can use a normal <code>return</code> without any additional labels:</p>
<ol>
<li>Named functions<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">regularNamed</span><span class="hljs-params">(isSleepy: <span class="hljs-type">Boolean</span>)</span></span> {
    <span class="hljs-keyword">if</span> (isSleepy) {
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">// do stuff</span>
}
</code></pre>
</li>
<li><p>Anonymous functions (do not confuse them with lambdas)</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">printEven</span><span class="hljs-params">(listOfInts: <span class="hljs-type">List</span>&lt;<span class="hljs-type">Int</span>&gt;)</span></span> {
    listOfInts.forEach(<span class="hljs-function"><span class="hljs-title">fun</span><span class="hljs-params">(x: <span class="hljs-type">Int</span>)</span></span> {
        <span class="hljs-keyword">if</span> (x % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) {
            println(x)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">/** 
            * This will return at the anonymous fun
            * and continue forEach iteration.
            * Lambda would have returned at printEven
            * since forEach is inlined.
            */</span>
            <span class="hljs-keyword">return</span>
        }
    })
}
</code></pre><blockquote>
<p>In most cases, we wouldn't use anonymous functions. However, keep in mind that anonymous functions allow us to specify an explicit return type, while lambdas don't.</p>
</blockquote>
</li>
<li><p>Inline functions</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">weAllFloat</span><span class="hljs-params">(list: <span class="hljs-type">List</span>&lt;<span class="hljs-type">Any</span>&gt;)</span></span> {
    list.forEach { 
        <span class="hljs-keyword">if</span> (it !<span class="hljs-keyword">is</span> <span class="hljs-built_in">Float</span>) {
            <span class="hljs-comment">/** 
            * Once again, forEach is inline
            * and will return at weAllFloat.
            * If we would like to continue looping,
            * we should use a local return<span class="hljs-doctag">@forEach</span>
            */</span>
            <span class="hljs-keyword">return</span>
        } <span class="hljs-keyword">else</span> {
            it.float() 🎈
        }
    }
}
</code></pre></li>
</ol>
<p>These are <strong>non-local returns</strong>.</p>
<p>To use a <code>return</code> inside a lambda, we must <em>use either a default or a custom label</em>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// not the cleanest code, but illustrates our point</span>
<span class="hljs-keyword">val</span> hasString = <span class="hljs-symbol">lambda@</span>{
    list.forEach { 
        <span class="hljs-keyword">if</span> (it <span class="hljs-keyword">is</span> String) {
            <span class="hljs-keyword">return</span><span class="hljs-symbol">@lambda</span> <span class="hljs-literal">true</span>
        }
    }
    <span class="hljs-keyword">return</span><span class="hljs-symbol">@lambda</span> <span class="hljs-literal">false</span>
}
print(hasString())
</code></pre>
<p>These are <strong>local returns</strong>.</p>
<p>The reason we can use a non-local <code>return</code> inside an inlined lambda is that it will just return from the enclosing function, where the code will be inlined.</p>
<h3 id="32-the-problem-and-the-crossinline-solution">3.2. The problem and the crossinline solution</h3>
<p>But there is a problem that can arise with the inlined lambdas and their non-local returns:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    inlineFunction {
        <span class="hljs-keyword">return</span> <span class="hljs-comment">// this is fine, no compile error here</span>
    }
}

<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">inlineFunction</span><span class="hljs-params">(inlineLambda: () -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    randomFunction {
        inlineLambda() <span class="hljs-comment">// compile error</span>
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">randomFunction</span><span class="hljs-params">(nonInlineLambda: () -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    nonInlineLambda()
}
</code></pre>
<p>The <code>nonInlineLambda</code> is a regular lambda and we cannot use a non-local return inside a regular lambda. Inline lambdas, however, allow non-local returns, and in this case, it would be inlined inside a regular lambda.</p>
<p>The compiler doesn't like that idea and since it cannot guarantee that we won't try to pass a non-local return inside an inline lambda to a regular function, it just doesn't allow passing inline lambdas to regular functions altogether.</p>
<p>We've had a very similar example in the <code>noinline</code> section, where we passed an inline lambda to the regular <code>withContext</code> function. In that case, the problem was solved by not inlining the lambda at all, which is one way to do it.</p>
<p>The other solution is the <code>crossinline</code> modifier. By marking a lambda parameter with <code>crossinline</code> we <em>prohibit using the non-local return inside that inline lambda</em>, and therefore can safely pass it to a regular function.</p>
<p>That said, let's fix our code:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    inlineFunction {
        <span class="hljs-comment">// the non-local return won't compile here anymore</span>
        <span class="hljs-keyword">return</span><span class="hljs-symbol">@inlineFunction</span>
    }
}

<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">inlineFunction</span><span class="hljs-params">(<span class="hljs-keyword">crossinline</span> inlineLambda: () -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    randomFunction {
        inlineLambda() <span class="hljs-comment">// now this is perfectly fine</span>
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">randomFunction</span><span class="hljs-params">(nonInlineLambda: () -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    nonInlineLambda()
}
</code></pre>
<p>Now we can have all the benefits of our <code>inlineLambda</code> and the compiler won't have to worry about non-local returns.</p>
<p>A good example of <code>crossinline</code> in the Kotlin standard library is the <code>sortBy</code> function:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T, R : Comparable&lt;R&gt;</span>&gt; MutableList<span class="hljs-type">&lt;T&gt;</span>.<span class="hljs-title">sortBy</span><span class="hljs-params">(
    <span class="hljs-keyword">crossinline</span> selector: (<span class="hljs-type">T</span>) -&gt; <span class="hljs-type">R</span>?
)</span></span>: <span class="hljs-built_in">Unit</span>
</code></pre><p>It passes the <code>selector</code> down to a regular function, but still inlines the comparator logic. </p>
<h2 id="4-reified-modifier">4. Reified modifier</h2>
<p>Finally, we got to the final modifier that we will discuss today. This is probably my favorite one since it allows for some clever solutions.</p>
<p>Let's take a look at a simple example:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> json = <span class="hljs-string">"{ ... }"</span>
    <span class="hljs-keyword">val</span> user = json.asObjectFromJson(User::<span class="hljs-keyword">class</span>.java)
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> String.<span class="hljs-title">asObjectFromJson</span><span class="hljs-params">(classType: <span class="hljs-type">Class</span>&lt;<span class="hljs-type">T</span>&gt;)</span></span>: T? {
    <span class="hljs-comment">// validate json</span>
    <span class="hljs-comment">// do some deserialization</span>
    <span class="hljs-comment">// return an instance of classType</span>
}
</code></pre>
<p>In a regular function, type <code>T</code> is <em>only available during compile time and is erased at runtime</em>. Therefore normally, we cannot infer the class of <code>T</code> at runtime and have to pass a <code>Class</code> as a parameter.</p>
<p>The <code>reified</code> modifier fixes this inconvenience. However, keep in mind that we can only use <code>reified</code> in the inlined functions.</p>
<p>Here is how we can improve our code using the <code>reified</code> modifier:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> json = <span class="hljs-string">"{ ... }"</span>
    <span class="hljs-comment">// the call looks prettier as well</span>
    <span class="hljs-keyword">val</span> user = json.asObjectFromJson&lt;User&gt;()
}

<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;<span class="hljs-keyword">reified</span> T&gt;</span> String.<span class="hljs-title">asObjectFromJson</span><span class="hljs-params">()</span></span>: T? {
    <span class="hljs-comment">// validate json</span>
    <span class="hljs-comment">// do some deserialization</span>
    <span class="hljs-comment">// we can access the class of T during runtime now!</span>
    <span class="hljs-keyword">return</span> T::<span class="hljs-keyword">class</span>.java.newInstance()
}
</code></pre>
<p>By marking our generic <code>T</code> as <code>reified</code> we can use it inside the function as if it was a normal class.</p>
<p>The <code>inline</code> function makes this possible without using reflection, however, if you need to use it, reflection also becomes available for the <code>reified</code> types as well as operators like <code>is</code> and <code>as</code> that work with classes.</p>
<p>One of the most common examples of <code>reified</code> in the Kotlin standard library is the <code>Iterable</code> extension function <code>filterIsInstance</code>:</p>
<pre><code><span class="hljs-keyword">list</span>.filterIsInstance&lt;<span class="hljs-keyword">String</span>&gt;()
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>When switching from Java to Kotlin, it can be very tempting to continue writing Java code, only using Kotlin. Kotlin will not stop you from doing that.</p>
<p>However, Kotlin offers so much more and any Kotlin user would be doing themselves a huge disservice by missing out on a huge variety of features that Kotlin provides.</p>
<p>Today we have looked at some of those features, and, hopefully, this information will help you write better idiomatic Kotlin code.</p>
<p>See you next time.</p>
<p><em>To growing and sharing,</em></p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Understanding Layouts in Jetpack Compose]]></title><description><![CDATA[In my previous article Things you need to know before switching to Jetpack Compose, I discussed the basic principles of building UI using Jetpack Compose. 
Today, let's dive a little deeper into how layouts work in Compose and learn how to build a mo...]]></description><link>https://maxkim.dev/understanding-layouts-in-jetpack-compose</link><guid isPermaLink="true">https://maxkim.dev/understanding-layouts-in-jetpack-compose</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[android apps]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Android Studio]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Sun, 25 Jul 2021 17:28:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627234201356/djlV76uIc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous article <a target="_blank" href="https://maxkim.eu/things-you-need-to-know-before-switching-to-jetpack-compose">Things you need to know before switching to Jetpack Compose</a>, I discussed the basic principles of building UI using Jetpack Compose. </p>
<p>Today, let's dive a little deeper into how layouts work in Compose and learn how to build a more complex UI.</p>
<h3 id="contents">Contents</h3>
<pre><code><span class="hljs-bullet">1.</span> The basics of layouting in Compose / Three basic layout
<span class="hljs-bullet">2.</span> Dissecting the layouts
<span class="hljs-bullet">3.</span> The Modifier. Size / Appearance / Interactivity
<span class="hljs-bullet">4.</span> Summary
</code></pre><h3 id="the-basics-of-layouting-in-compose">The basics of layouting in Compose</h3>
<p><strong>Before we begin</strong></p>
<p>Nesting layouts in <code>.XML</code>s, is considered very bad practice since the performance hit due to remeasuring and recalculating the position of children is quite noticeable, especially when nesting more heavyweight layouts.</p>
<p>One of the main differences in Compose that fundamentally changes how we structure UI is that Compose <em>doesn't allow measuring of layout children more than once</em>. In fact, it will even throw a <code>RuntimeException</code> if that ever happens.</p>
<p>Therefore, you can <em>nest composables as much as you like</em> without worrying about performance.</p>
<p><strong>With that out of the way, let's dive in!</strong></p>
<p>The first thing to remember about composable functions is that they don't return anything, or rather they return <code>Unit</code> since we live in the Kotlin world. This might confuse some folk coming from React Native or Flutter, where similar functions do return components or widgets to build UI.</p>
<p>In Compose, we <em>describe</em> our UI, and every composable we put inside a composable function will be reflected on the screen in one way or another.</p>
<p>For example:</p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Haiku</span><span class="hljs-params">()</span></span> {
    Text(text = <span class="hljs-string">"I write, erase, rewrite"</span>)
    Text(text = <span class="hljs-string">"Erase again, and then"</span>)
    Text(text = <span class="hljs-string">"A poppy blooms."</span>)
}
</code></pre><p>This is a perfectly fine composable, which draws every one of the <code>Text</code> composables on the screen.</p>
<p>However, we didn't specify how exactly we want to display our lines of text, and therefore we get a quite predictable result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1626731384470/0Zv0XXGOb.png" alt="Screenshot 2021-07-20 at 00.49.16.png" /></p>
<p><strong>Three basic layouts</strong></p>
<p>If you have read my previous article, you might remember that we have used a <code>Row</code> to display the elements one after the other, or in other words <em>in a row</em>.</p>
<p>It would only make sense then to have another layout composable called <code>Column</code>. And, in fact, we do.</p>
<p>These are the main building blocks of UI in Compose. In most cases, we will use a combination of <code>Row</code>s and <code>Column</code>s to get the desired result.</p>
<p>There is another basic layout that we can use, called <code>Box</code>.</p>
<p>Here is an illustration of these basic layouts, courtesy of the official Compose <a target="_blank" href="https://developer.android.com/jetpack/compose/layouts/basics">documentation</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1626894816459/we0OBB3x3.png" alt="basic_layouts.png" /></p>
<p>Speaking about how these layouts stack children, we could say that:</p>
<ul>
<li><code>Column</code> is similar to vertical <code>LinearLayout</code>;</li>
<li><code>Row</code> is similar to horizontal <code>LinearLayout</code>;</li>
<li><code>Box</code> is similar to <code>FrameLayout</code>.</li>
</ul>
<p>But please keep in mind that <em>these composable layouts are much more than their imperative counterparts</em>. In fact, in most cases, these three layouts are all you need to build any UI. Using only <code>LinearLayout</code>s to build our UI would be a huge no-no. However, since <em>nesting in Compose doesn't affect performance</em> - this is the standard way here. </p>
<blockquote>
<p>Note: There is a <code>ConstraintLayout</code> in Compose that allows a more sophisticated layouting. I will probably write a separate article about it but keep in mind that even though <code>ConstraintLayout</code> was a recommended way to build layouts until now to avoid nesting layouts, in Jetpack Compose, you don't actually need it.</p>
</blockquote>
<p><strong>Now, let's return to our haiku and try to fix it.</strong></p>
<p>In order to display the <code>Text</code> lines in a column, all we have to do is to wrap them inside a <code>Column</code> composable:</p>
<pre><code>@Composable
fun Haiku() {
    <span class="hljs-keyword">Column</span> {
        Text(<span class="hljs-type">text</span> = "I write, erase, rewrite")
        Text(<span class="hljs-type">text</span> = "Erase again, and then")
        Text(<span class="hljs-type">text</span> = "A poppy blooms.")
    }
}
</code></pre><p>Which gives us the desired outcome:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1626976769836/rZwPsyHKv.png" alt="Screenshot 2021-07-22 at 20.58.55.png" /></p>
<p>One thing to keep in mind here is that if you don't specify the layout of the children, they <em>will be affected by the parent of the composable</em>.</p>
<p>For example, the following code will give us the same result:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            <span class="hljs-comment">// This Column will affect the contents of our composable</span>
            Column {
                Haiku()
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Haiku</span><span class="hljs-params">()</span></span> {
    Text(text = <span class="hljs-string">"I write, erase, rewrite"</span>)
    Text(text = <span class="hljs-string">"Erase again, and then"</span>)
    Text(text = <span class="hljs-string">"A poppy blooms."</span>)
}
</code></pre><p>But in this case, the composable has no say in <em>how its children will be laid out</em>. If someone calls our <code>Haiku</code> from the context of a <code>Row</code> layout, our composable will produce an undesired result. Therefore, this approach is not recommended, just something to keep in mind for educational purposes.</p>
<h3 id="dissecting-the-layouts">Dissecting the layouts</h3>
<p>As I have said before, these basic layouts are much more than meets the eye. In fact, they provide us with everything we might need to build UI.</p>
<p>Let's see what we can do with them.</p>
<p>For that, here is <strong><em>a quick tip</em></strong> for those who don't use shortcuts much.</p>
<p>You can press <code>CMD/Ctrl + P</code> inside a constructor's or function's argument brackets, and Android Studio will show every possible argument with default values.</p>
<blockquote>
<p>Note: you can also do it inside the trailing lambda since technically, it is an argument you pass.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627120746613/WNVvIptOB.png" alt="Screenshot 2021-07-24 at 12.52.59.png" /></p>
<p>I cropped this image a bit to be legible on smaller screens, but you get the point.</p>
<p>This way, you can always see what options are available to you. And if you need some additional information, nothing beats opening a source code and reading the declaration.</p>
<p>With that out of the way, let's see what we can do with our <code>Column</code>.</p>
<p><strong>The Column</strong></p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Column</span><span class="hljs-params">(
    modifier: <span class="hljs-type">Modifier</span> = Modifier,
    verticalArrangement: <span class="hljs-type">Arrangement</span>.<span class="hljs-type">Vertical</span> = Arrangement.Top,
    horizontalAlignment: <span class="hljs-type">Alignment</span>.<span class="hljs-type">Horizontal</span> = Alignment.Start,
    content: @<span class="hljs-type">Composable</span> <span class="hljs-type">ColumnScope</span>.() -&gt; <span class="hljs-type">Unit</span>
)</span></span>
</code></pre><p>At first glance, there isn't much. However, the first parameter that takes in a <code>Modifier</code> is a true powerhouse in the Compose world, and <em>you will be using it a lot</em>.</p>
<p>Let's leave it for now and take a look at the other parameters.</p>
<p><strong>The content</strong></p>
<p>The <code>content</code> is a function with a <code>ColumnScope</code> as a receiver. If you are not familiar with this Kotlin concept, you can <a target="_blank" href="https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver">read about it here</a>. What it does is it makes the <code>ColumnScope</code> as <code>this</code> inside the function.</p>
<p>This is the <em>content we want to display inside</em> our Column.</p>
<p><strong>The horizontalAlignment</strong></p>
<p><code>horizontalAlignment</code> defines how we align our content horizontally, and all the expected options are supported:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627123520780/D5NW6IBiQ.png" alt="Screenshot 2021-07-24 at 13.44.42.png" /></p>
<p>However, please note that arguments of type <code>Alignment.Vertical</code> will not be accepted here. Those are used in the <code>Row</code> layout.</p>
<p><strong>The verticalArrangement</strong></p>
<p>The idea of arrangement might be new to some people coming to declarative UI. Still, even in the imperative approach, we had a similar concept when defining how to position chained items inside a <code>ConstraintLayout</code>.</p>
<p><code>verticalArrangement</code> defines how children will be arranged along the height of the column.</p>
<p>Here are the available options for <code>Arrangement.Vertical</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627127557337/qU9oHtf-6.png" alt="Screenshot 2021-07-24 at 14.52.22.png" /></p>
<p>And before we tackle the <code>modifier</code>, let's take a look at the arrangement/alignment options for the other basic layouts.</p>
<p><strong>The Row</strong></p>
<p>The <code>Row</code> is pretty much the same as the <code>Column</code>:</p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Row</span><span class="hljs-params">(
    modifier: <span class="hljs-type">Modifier</span> = Modifier,
    horizontalArrangement: <span class="hljs-type">Arrangement</span>.<span class="hljs-type">Horizontal</span> = Arrangement.Start,
    verticalAlignment: <span class="hljs-type">Alignment</span>.<span class="hljs-type">Vertical</span> = Alignment.Top,
    content: @<span class="hljs-type">Composable</span> <span class="hljs-type">RowScope</span>.() -&gt; <span class="hljs-type">Unit</span>
)</span></span>
</code></pre><p>The main difference is that the <code>Arrangement</code> and <code>Alignment</code> are switched.</p>
<p>The <code>verticalAlignment</code> therefore takes an <code>Alignment.Vertical</code> as an argument, which has all the usual alignments.</p>
<p>And <code>horizontalArrangement</code> takes the <code>Arrangement.Horizontal</code> object, where <code>Arrangement.Top</code> becomes <code>Arrangement.Start</code> and <code>Arrangement.Bottom</code> becomes <code>Arrangement.End</code>.</p>
<p><strong>The Box</strong></p>
<p>Lastly, we have the <code>Box</code>.</p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Box</span><span class="hljs-params">(
    modifier: <span class="hljs-type">Modifier</span> = Modifier,
    contentAlignment: <span class="hljs-type">Alignment</span> = Alignment.TopStart,
    propagateMinConstraints: <span class="hljs-type">Boolean</span> = <span class="hljs-literal">false</span>,
    content: @<span class="hljs-type">Composable</span> <span class="hljs-type">BoxScope</span>.() -&gt; <span class="hljs-type">Unit</span>
)</span></span>
</code></pre><p>As we have mentioned, the <code>Box</code> behaves similar to <code>FrameLayout</code> when arranging children, therefore there is no <code>Arrangement</code> parameter. We can only specify the <code>Alignment</code>, which has all the alignments we would expect to find there.</p>
<p>The <code>propagateMinConstraints</code> is nothing to concern ourselves about given the scope of this article, but for some quick info, we can refer to the KDoc: </p>
<p><em>If propagateMinConstraints is set to true, the min size set on the Box will also be applied to the content, whereas otherwise, the min size will only apply to the Box.</em></p>
<h3 id="the-modifier">The Modifier</h3>
<p>With that, we come to the <code>modifier</code>. Although we are talking about layouts today, you can apply the <code>Modifier</code> to any composable, which allows us to, yes, you've guessed it, <em>modify</em> the composable. And layouts are composables, after all.</p>
<p>There are a lot of things we can do with the <code>Modifier</code>, but for the sake of keeping this article at a manageable size, we will only look at the most common use cases.</p>
<p>That said, first things first. Before looking into specific modifiers, let's once again start by understanding <em>what the</em> <code>Modifier</code> <em>object really is</em>.</p>
<p><strong>Under the hood</strong></p>
<p>Here is what we can find in the declaration.</p>
<pre><code><span class="hljs-comment">/**
* An ordered, immutable collection of modifier elements 
* that decorate or add behavior to Compose UI elements.
* For example, backgrounds, padding, and click event listeners 
* decorate or add behavior to rows, text, or buttons.
*/</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Modifier</span></span>
</code></pre><p>We can see that the <code>Modifier</code> represents a collection of <em>modifier elements</em> that change the appearance or behavior of composables.</p>
<p>The <code>Modifier.Element</code> is also a simple interface. Every modification that we can apply to composables implements this interface, which allows it to be stacked into a Modifier chain.</p>
<pre><code><span class="hljs-comment">/**
* A single element contained within a Modifier chain.
*/</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Element</span> : <span class="hljs-type">Modifier</span></span>
</code></pre><p>There are a lot of <code>Modifier.Element</code>s that Compose gives us out of the box, and as you can see, this approach is <em>very flexible</em> and allows us to write <em>custom modifiers</em> if needed.</p>
<p>By clicking the green <code>I↓</code> button next to the declaration, we can see all the available Modifiers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627216577465/BZzzZFxmR.png" alt="Screenshot 2021-07-25 at 15.35.08.png" /></p>
<p>There are <code>Background</code>, <code>SizeModifier</code>, <code>PaddingModifier</code>, and many others that we will regularly use in Compose.</p>
<p>Don't worry, you don't need to memorize these implementations. Or, to be frank, even know that they exist.</p>
<p>I just wanted to dig a little bit deeper and show how it all works for educational purposes. Compose <em>provides us with simple and intuitive DSL for using modifiers</em> and you won't need to know the specifics of the implementation if you don't want to. However, I believe that knowing how the stuff we regularly use works makes us much better developers.</p>
<p><strong>How chaining modifiers works</strong></p>
<p>As you might have already seen in my previous article, we can use the modifiers as follows:</p>
<pre><code>@Composable
fun Haiku() {
    <span class="hljs-keyword">Column</span>(
        modifier = Modifier
            .fillMaxWidth()
            .padding(<span class="hljs-number">10.</span>dp)
            .background(
                color = Color.Blue
            )
    ) {
        Text(<span class="hljs-type">text</span> = "I write, erase, rewrite")
        Text(<span class="hljs-type">text</span> = "Erase again, and then")
        Text(<span class="hljs-type">text</span> = "A poppy blooms.")
    }
}
</code></pre><p>This is how a chain of modifiers looks in code.</p>
<blockquote>
<p>Note: Please keep in mind that the modifiers will be applied in the specified order, which has an effect on how the final result will look.
For example, in the code above, the padding will be applied before the background. Therefore, the blue background will be inside the padding, and the padding itself won't have any color.
If we had specified the padding after the background, then the whole composable's background would be blue, including the padding.</p>
</blockquote>
<p>And before I bore you to death with going through the source code, let's take a look at it one last time and see how it all comes together.</p>
<p>Let's take <code>.padding()</code> as an example:</p>
<pre><code>fun Modifier.padding(<span class="hljs-keyword">all</span>: Dp) =
    this.<span class="hljs-keyword">then</span>(
        PaddingModifier(
            start = <span class="hljs-keyword">all</span>,
            top = <span class="hljs-keyword">all</span>,
            end = <span class="hljs-keyword">all</span>,
            bottom = <span class="hljs-keyword">all</span>,
            rtlAware = <span class="hljs-keyword">true</span>,
            inspectorInfo = debugInspectorInfo {
                <span class="hljs-type">name</span> = "padding"
                <span class="hljs-keyword">value</span> = <span class="hljs-keyword">all</span>
            }
        )
    )
</code></pre><p>It is a simple Kotlin extension function that creates a new <code>PaddingModifier</code>, which implements <code>Modifier.Element</code>, and passes it to the existing <code>Modifier</code> through the <code>then</code> function.</p>
<pre><code><span class="hljs-comment">/**
* Concatenates this modifier with another.
* Returns a Modifier representing this modifier 
* followed by other in sequence.
*/</span>
<span class="hljs-keyword">infix</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">then</span><span class="hljs-params">(other: <span class="hljs-type">Modifier</span>)</span></span>: Modifier =
        <span class="hljs-keyword">if</span> (other === Modifier) <span class="hljs-keyword">this</span> <span class="hljs-keyword">else</span> CombinedModifier(<span class="hljs-keyword">this</span>, other)
</code></pre><p>As you can see, the <code>then</code> function adds a new <code>Modifier</code> to the existing chain and returns the resulting <code>Modifier</code> so that the chain can continue.</p>
<p>Not that we know how <code>Modifier</code> works, let's finally look at some of the most used modifiers.</p>
<p><strong>Modifying the size</strong></p>
<p>Most commonly, the <code>Modifier</code> is used for specifying the size of a composable.</p>
<pre><code><span class="hljs-comment">// Set the width and/or height of a composable </span>
<span class="hljs-comment">// to specific size in Dp</span>
<span class="hljs-selector-class">.width</span>(<span class="hljs-attribute">width</span>: Dp)
<span class="hljs-selector-class">.height</span>(<span class="hljs-attribute">height</span>: Dp)
</code></pre><pre><code><span class="hljs-comment">// Fill all available space for width and/or height</span>
<span class="hljs-comment">// Equivalent of "match_parent"</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">// Can be specified with a fraction argument</span>
<span class="hljs-comment">// to fill a fraction of available space</span>
<span class="hljs-selector-class">.fillMaxWidth</span>(<span class="hljs-attribute">fraction</span>: Float = <span class="hljs-number">1</span>f)
<span class="hljs-selector-class">.fillMaxHeight</span>(<span class="hljs-attribute">fraction</span>: Float = <span class="hljs-number">1</span>f)
</code></pre><pre><code><span class="hljs-comment">// Fill all available space for both width and height</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">// Can be specified with a fraction argument</span>
<span class="hljs-comment">// to fill a fraction of available space</span>
<span class="hljs-selector-class">.fillMaxSize</span>(<span class="hljs-attribute">fraction</span>: Float = <span class="hljs-number">1</span>f)
</code></pre><p><strong>Modifying the appearance</strong></p>
<p>And here are some common <code>Modifier</code>s that are used for changing the appearance of a composable.</p>
<pre><code><span class="hljs-comment">// Adds padding to the composable</span>
<span class="hljs-selector-class">.padding</span>(<span class="hljs-attribute">all</span>: Dp)
<span class="hljs-selector-class">.padding</span>(
    <span class="hljs-attribute">horizontal</span>: Dp = <span class="hljs-number">0</span>.dp,
    <span class="hljs-attribute">vertical</span>: Dp = <span class="hljs-number">0</span>.dp
)
<span class="hljs-selector-class">.padding</span>(
    <span class="hljs-attribute">start</span>: Dp = <span class="hljs-number">0</span>.dp,
    <span class="hljs-attribute">top</span>: Dp = <span class="hljs-number">0</span>.dp,
    <span class="hljs-attribute">end</span>: Dp = <span class="hljs-number">0</span>.dp,
    <span class="hljs-attribute">bottom</span>: Dp = <span class="hljs-number">0</span>.dp
)
</code></pre><pre><code><span class="hljs-comment">// Modifies the alpha/scale/rotation</span>
<span class="hljs-selector-class">.alpha</span>(<span class="hljs-attribute">alpha</span>: Float)
<span class="hljs-selector-class">.scale</span>(<span class="hljs-attribute">scale</span>: Float)
<span class="hljs-selector-class">.scale</span>(<span class="hljs-attribute">scaleX</span>: Float, <span class="hljs-attribute">scaleY</span>: Float)
<span class="hljs-selector-class">.rotate</span>(<span class="hljs-attribute">degrees</span>: Float)
</code></pre><pre><code><span class="hljs-comment">// Specifies the color and shape of the background</span>
<span class="hljs-selector-class">.background</span>(
    <span class="hljs-attribute">color</span>: Color,
    <span class="hljs-attribute">shape</span>: Shape = RectangleShape
)
</code></pre><pre><code><span class="hljs-comment">// Adds a border</span>
<span class="hljs-selector-class">.border</span>(
    <span class="hljs-attribute">width</span>: Dp,
    <span class="hljs-attribute">color</span>: Color,
    <span class="hljs-attribute">shape</span>: Shape = RectangleShape
)
</code></pre><pre><code><span class="hljs-comment">// Clips the content to shape or bounds</span>
<span class="hljs-selector-class">.clip</span>(<span class="hljs-attribute">shape</span>: Shape)
<span class="hljs-selector-class">.clipToBounds</span>()
</code></pre><p><strong>Modifying the interactivity</strong></p>
<p><code>Modifier</code>s are also used to describe the behavior of a composable, or, in other words, how we can interact with it.</p>
<pre><code><span class="hljs-comment">// Adds click functionality to the composable</span>
<span class="hljs-comment">// Use .combinedClickable for long clicks and double clicks</span>
<span class="hljs-selector-class">.clickable</span>(
    <span class="hljs-attribute">enabled</span>: Boolean = true,
    <span class="hljs-attribute">onClick</span>: () -&gt; Unit
)
</code></pre><pre><code><span class="hljs-comment">// Adds scrolling functionality to the composable</span>
<span class="hljs-comment">// Yes, anything can become a ScrollView!</span>
<span class="hljs-selector-class">.verticalScroll</span>(
    <span class="hljs-attribute">state</span>: ScrollState,
    <span class="hljs-attribute">enabled</span>: Boolean = true,
)
<span class="hljs-selector-class">.horizontalScroll</span>(
    <span class="hljs-attribute">state</span>: ScrollState,
    <span class="hljs-attribute">enabled</span>: Boolean = true,
)
</code></pre><pre><code><span class="hljs-comment">// Adds focus listener to the composable </span>
<span class="hljs-selector-class">.onFocusChanged</span>(<span class="hljs-attribute">onFocusChanged</span>: (FocusState) -&gt; Unit)
<span class="hljs-comment">// Adds key event listener to the composable </span>
<span class="hljs-selector-class">.onKeyEvent</span>(<span class="hljs-attribute">onKeyEvent</span>: (KeyEvent) -&gt; Boolean)
<span class="hljs-comment">// Adds size listener to the composable </span>
<span class="hljs-selector-class">.onSizeChanged</span>(<span class="hljs-attribute">onSizeChanged</span>: (IntSize) -&gt; Unit)
<span class="hljs-comment">/// ... and other listeners</span>
</code></pre><p>Of course, this is just scratching the surface of what we can do in Compose through modifiers, but this gives a pretty good idea about how things work in this new toolkit.</p>
<h3 id="summary">Summary</h3>
<p>We have gone through a lot of information today, haven't we?</p>
<p>Thanks a lot for sticking until the end.</p>
<p><strong>Just to recap:</strong></p>
<p>In Compose, almost everything can be drawn with <code>Row</code>s, <code>Column</code>s, and an occasional <code>Box</code>. There is no need for complex layouts like <code>ConstraintLayout</code> since <em>nesting elements don't affect the performance</em> as it was in the old days. </p>
<p>Compose is very flexible and gives us many ways how to align and arrange elements. As well as style and add behavior to our composables through the <code>Modifier</code> object that allows us to achieve almost any result right out of the box. And if not, you can always write your own modifiers and custom layouts.</p>
<p>And of course, <em>there is no better way to learn things than doing them yourself</em>. So fire up Android Studio, play around with Compose, and see how it works.</p>
<p>But keep in mind that it can become quite fun and addictive when you get a grip on it.</p>
<p>Until next time,</p>
<p><em>Your friend,</em></p>
<p><em>Max</em></p>
]]></content:encoded></item><item><title><![CDATA[Things you need to know before switching to Jetpack Compose]]></title><description><![CDATA[With the release of the stable version of Jetpack Compose just around the corner, here are some things you need to know before switching from the imperative, XML-based style for building UI, to the new Android’s toolkit for building native UI declara...]]></description><link>https://maxkim.dev/things-you-need-to-know-before-switching-to-jetpack-compose</link><guid isPermaLink="true">https://maxkim.dev/things-you-need-to-know-before-switching-to-jetpack-compose</guid><category><![CDATA[Android]]></category><category><![CDATA[android apps]]></category><category><![CDATA[Android Studio]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Mon, 12 Jul 2021 09:39:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1625693138062/_rlN91Wnz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the release of the stable version of <a target="_blank" href="https://developer.android.com/jetpack/compose">Jetpack Compose</a> just around the corner, here are some things you need to know before switching from the <em>imperative</em>, XML-based style for building UI, to the new Android’s toolkit for building native UI <em>declaratively</em>.</p>
<h3 id="first-lets-get-the-basics-out-of-the-way">First, let's get the basics out of the way</h3>
<p>What does it mean to build UI <em>declaratively</em> rather than <em>imperatively</em>? Let's quickly break down the main difference between these two styles.</p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Imperative_programming">imperative</a> style focuses on <em>how</em>. You provide step-by-step instructions on <em>how</em> you would like to get to your desired result. This is how we were building UI in Android applications all this time. The simplified illustration of the imperative style would be:</p>
<pre><code><span class="hljs-deletion">-&gt; Go to the kitchen.</span>
<span class="hljs-deletion">-&gt; Open the fridge.</span>
<span class="hljs-deletion">-&gt; Take eggs from the fridge.</span>
<span class="hljs-deletion">-&gt; Put eggs in a pan.</span>
<span class="hljs-deletion">-&gt; Wait 5 minutes.</span>
<span class="hljs-deletion">-&gt; Put eggs from the pan on a plate.</span>
</code></pre><p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Declarative_programming">declarative</a> style, on the other hand, focuses on <em>what</em>. You describe <em>what</em> result you want to achieve. The above example would look something like this:</p>
<pre><code><span class="hljs-deletion">-&gt; I want fried eggs.</span>
</code></pre><p>The declarative approach does remove quite a lot of boilerplate, provided you have a buddy who knows how to cook. Luckily for us, in the Android UI building world, Jetpack Compose is that buddy.</p>
<p>Other examples of building UI declaratively in the mobile development are  <a target="_blank" href="https://reactnative.dev/">ReactNative</a>, <a target="_blank" href="https://flutter.dev/">Flutter</a>, and <a target="_blank" href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a>.</p>
<h3 id="how-to-use-compose-for-building-ui">How to use Compose for building UI</h3>
<p>To draw UI, Compose uses regular Kotlin functions annotated with <code>@Composable</code>. Therefore, these functions are often referred to as <em>composables</em>. </p>
<p><strong>Here are some key points regarding composable functions to keep in mind:</strong></p>
<ul>
<li>Composable functions can only be called from <em>within the scope of other composable functions</em>.</li>
</ul>
<ul>
<li>Composable functions <em>don't return anything</em>. They don't return any Views or Widgets but rather <em>describe the UI</em>.</li>
</ul>
<ul>
<li>Composable functions <em>can take in arguments</em> and you <em>can use regular Kotlin expressions</em> within the composable function as you would within regular functions.</li>
</ul>
<ul>
<li>Composable functions <em>should behave the same way</em> when called multiple times with the same arguments, <em>without using or modifying global properties and variables</em>.</li>
</ul>
<ul>
<li>As opposed to the regular naming convention of functions in Kotlin, names of composable functions <em>start with a capital letter</em>.</li>
</ul>
<p>With that out of the way, let's look at how to use Jetpack Compose in practice.</p>
<p><strong>Let's say we need to build the following UI element:</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625689187885/lZ21xiV7e.png" alt="Screenshot 2021-07-07 at 23.19.35.png" /></p>
<p><strong>Now, to achieve this result, we need to describe the following things in our composable function:</strong></p>
<ul>
<li>We need a <code>Text</code> and a <code>Checkbox</code>, arranged in a <code>Row</code>, with some <code>Space</code> in between.</li>
</ul>
<ul>
<li>The whole <code>Row</code> should be <em>modified</em> to have a gray <code>RoundedBorder</code> and some <code>Padding</code> to let the elements inside breathe.</li>
</ul>
<ul>
<li>The elements inside should be <code>CenteredVertically</code>, for a more pleasant look.</li>
</ul>
<p>Let's create our Composable and, without being too preoccupied with the syntax at this stage, see how our description looks in Kotlin:</p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">FollowTheBlog</span><span class="hljs-params">()</span></span> {
    Row(
        modifier = Modifier
            .border(
                width = <span class="hljs-number">1</span>.dp,
                color = Color.Gray,
                shape = RoundedCornerShape(<span class="hljs-number">5</span>.dp)
            )
            .padding(<span class="hljs-number">14</span>.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(<span class="hljs-string">"Check to follow the blog for awesome content!"</span>)
        Spacer(modifier = Modifier.width(<span class="hljs-number">8</span>.dp))
        Checkbox(
            checked = <span class="hljs-literal">false</span>,
            onCheckedChange = { checked -&gt;
                <span class="hljs-comment">// some follow the blog action</span>
            }
        )
    }
}
</code></pre><p>This code should be quite intuitive and easy to read, even for those not fluent in Kotlin, which is a major step up from how we used to build our Android UI.</p>
<p>Now, if we run our composable, it will indeed produce the desired result in terms of visuals but, if we try to interact with it, we will notice some unexpected behavior:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625690180547/IbAPVFRgD.gif" alt="blog_click_checkbox.gif" /></p>
<h3 id="the-single-source-of-truth">The Single Source of Truth</h3>
<p>The main premise of Jetpack Compose is to <em>represent the current state</em> of UI on the screen and, as opposed to when using views, clicking the checkbox emitted by Compose doesn't visually change it because we <em>haven't changed the state</em> of our UI.</p>
<p>Coming from the imperative style of building UI, this approach might seem unintuitive and redundant, but this is one of the <em>key concepts</em> in declarative UI.</p>
<p>The main benefit of this approach is that Compose makes it <em>much easier to manage the state of UI in one place</em>. This allows us to draw UI based on a <em>single source of truth</em> - the current state of UI - without needing to synchronize the state between multiple components, as was often the case when using an XML/View-based approach.</p>
<h3 id="understanding-state">Understanding State</h3>
<p>Since composable functions represent the state of UI, the only way to update UI is to <em>run the composable function again</em> but with different arguments representing the current state. In Compose, this is called <em>Recomposition</em>.</p>
<p>So if we look at our code above, we see that we have <em>described</em> our <code>Checkbox</code> with an argument <code>checked = false</code>, which is exactly what we got.</p>
<p><strong> Considering this, we could fix our checkbox with the following steps:</strong></p>
<ul>
<li>When describing our <code>Checkbox</code>, we will set the parameter <code>checked</code> to <em>a variable</em>.</li>
</ul>
<ul>
<li>We will <em>toggle</em> that variable in the <code>onCheckedChange</code> callback.</li>
</ul>
<ul>
<li>We need that variable <em>to persist</em> between the recompositions.</li>
</ul>
<ul>
<li>We need <em>to trigger</em> the recomposition when the user clicks the checkbox.</li>
</ul>
<p>The first two steps are quite straightforward. It could look something like this:</p>
<pre><code>Checkbox(
    <span class="hljs-keyword">checked</span> = isChecked,
    onCheckedChange = { <span class="hljs-keyword">checked</span> -&gt;
        isChecked = <span class="hljs-keyword">checked</span>
        <span class="hljs-comment">// some follow the blog action</span>
    }
)
</code></pre><p>The last two steps, however, might present some challenges for people new to Compose.</p>
<p><strong>Let's break them down. </strong></p>
<p>First, we need to persist the value of the <code>isChecked</code> variable between recompositions or, in other words, multiple runs of the function. The first answer that comes to mind would be to declare it as a global variable outside the scope of the composable function. </p>
<p>However, those who paid attention earlier would notice that this would violate one of the key points: </p>
<ul>
<li>...<em>without using or modifying global properties and variables</em> </li>
</ul>
<p>Moreover, the state of a checkbox represents the <em>local state</em> - other components don't necessarily need to know or influence how the checkbox is rendered.</p>
<p>Therefore, a better solution would be to manage this state inside our composable function, but it takes us back to square one with our persistence problem.</p>
<p>Luckily for us, Compose has an elegant built-in solution for this problem, as well as the problem with triggering the recomposition.</p>
<p><em>Here is how this solution looks</em>: </p>
<pre><code><span class="hljs-keyword">var</span> isChecked <span class="hljs-keyword">by</span> remember { mutableStateOf(<span class="hljs-literal">false</span>) }
</code></pre><p>This one line can be quite a brain bender for people who are new to Compose and/or are not used to more advanced Kotlin syntax, so let's break it down.</p>
<h4 id="first-lets-take-a-look-at-the-mutablestateof-function">First, let's take a look at the <code>mutableStateOf</code> function.</h4>
<p>If you have read my previous blog post <a target="_blank" href="https://maxkim.eu/7-tips-for-becoming-a-better-developer">7 Tips for Becoming a Better Developer</a>, you know that I like to dive into the source code to understand the API of a framework better, so buckle up.</p>
<p>The signature of this function is as follows:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">mutableStateOf</span><span class="hljs-params">(
    value: <span class="hljs-type">T</span>,
    policy: <span class="hljs-type">SnapshotMutationPolicy</span>&lt;<span class="hljs-type">T</span>&gt; = structuralEqualityPolicy()</span></span>
): MutableState&lt;T&gt;
</code></pre><p>We can see that this function takes in a <code>value</code> of generic type and returns an object implementing an <code>interface MutableState&lt;T&gt; : State&lt;T&gt;</code>. The <code>policy</code> parameter has a default value so let's not concern ourselves with it for the time being.</p>
<p>The <code>value</code> represents the initial value of that state, and in our case, we pass <code>false</code> for our checkbox to be unchecked.</p>
<p>If we go down the rabbit hole into the source code to find the actual implementation of our <code>MutableState</code> object, we will find: </p>
<pre><code><span class="hljs-comment">/**
* A single value holder whose reads and writes are observed by Compose.
* ...
*/</span>
<span class="hljs-type">internal</span> <span class="hljs-keyword">open</span> <span class="hljs-keyword">class</span> SnapshotMutableStateImpl&lt;T&gt;(
    <span class="hljs-keyword">value</span>: T,
    override val <span class="hljs-keyword">policy</span>: SnapshotMutationPolicy&lt;T&gt;
) : StateObject, SnapshotMutableState&lt;T&gt;
</code></pre><p>The most important part is the first line of the KDoc.</p>
<p>Without getting stuck on the implementation details, we can see that this state object acts as an <em>observable</em>.</p>
<p>In practice, it means that Compose will <em>observe our state</em> and when the value changes it will <em>schedule a recomposition</em> of any composable subscribed to it.</p>
<p>The composable <em>subscribes</em> to a state when <em>it reads its value</em>.</p>
<p>In other words - when setting the initial value, the composable will subscribe to changes in our state. As soon as we change the state inside the <code>onCheckedChange</code> callback, it will trigger the recomposition.</p>
<h4 id="next-is-the-remember-function">Next is the <code>remember { }</code> function.</h4>
<pre><code>
<span class="hljs-comment">/**
 * Remember the value produced by [calculation].
 * [calculation] will only be evaluated during the composition.
 * Recomposition will always return the value produced by composition.
 */</span>
<span class="hljs-variable">@Composable</span>
inline fun &lt;T&gt; remember(
     <span class="hljs-attribute">calculation</span>: <span class="hljs-variable">@DisallowComposableCalls</span> () -&gt; T
): T
</code></pre><p>The implementation details of this function can seem quite tricky, especially for less experienced programmers, but once again, reading the KDoc is more than enough for understanding what the function does.</p>
<p><em>The key takeaway is as follows:</em></p>
<p>As opposed to regular Kotlin functions, composable functions <em>have a memory</em> which persists across recompositions and even across configuration changes. <code>remember</code> function allows you to access that memory during recompositions. This means that by wrapping our state inside the <code>remember</code> function, we allow Compose <em>to access its value during the next recomposition</em>.</p>
<p>This means that when we change the value inside the <code>isChecked</code> state and trigger recomposition, the next time our function runs, it will <em>remember</em> our value. </p>
<p>Please note that <code>remember</code> doesn't work for configuration changes. For that, we would use a similar function <code>rememberSaveable</code>, which uses <code>Bundle</code> under the hood.</p>
<h4 id="lastly-we-have-the-by-keyword">Lastly, we have the <code>by</code> keyword.</h4>
<p>This is a feature of Kotlin called <a target="_blank" href="https://kotlinlang.org/docs/delegated-properties.html">Delegated Properties</a>. It allows manual implementation of the setter and the getter of a property.</p>
<p>In this case, it unwraps the value property inside the <code>MutableState</code> object and allows us to access it as we would a regular property. </p>
<p>Without it:</p>
<pre><code><span class="hljs-keyword">var</span> isChecked = remember { mutableStateOf(<span class="hljs-literal">false</span>) }
</code></pre><p>We would have to access the <code>value</code> of our state directly:</p>
<pre><code>Checkbox(
    <span class="hljs-keyword">checked</span> = isChecked.<span class="hljs-keyword">value</span>,
    onCheckedChange = { <span class="hljs-keyword">checked</span> -&gt;
        isChecked.<span class="hljs-keyword">value</span> = <span class="hljs-keyword">checked</span>
        <span class="hljs-comment">// some follow the blog action</span>
    }
)
</code></pre><p><em>Note: As of writing this post, you have to manually add the following imports for the <code>by</code> keyword to work correctly.</em></p>
<pre><code><span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">androidx</span><span class="hljs-selector-class">.compose</span><span class="hljs-selector-class">.runtime</span><span class="hljs-selector-class">.getValue</span>
<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">androidx</span><span class="hljs-selector-class">.compose</span><span class="hljs-selector-class">.runtime</span><span class="hljs-selector-class">.setValue</span>
</code></pre><p><strong>In summary, here is what we have achieved with that line: </strong></p>
<ul>
<li>We have created a <code>isChecked</code> variable, which is a <em>state</em>. </li>
</ul>
<ul>
<li>The Compose will subscribe to our state during the initial composition when setting the initial value. The value writes that happen in the <code>onCheckedChange</code> callback will trigger recomposition.</li>
</ul>
<ul>
<li>During the recomposition, Compose will <em>remember</em> the value of the state from the initial composition and render UI correctly.</li>
</ul>
<ul>
<li>We have used an advanced Kotlin feature to unwrap the value of our state so that we can use it as a regular property.</li>
</ul>
<h3 id="how-it-all-comes-together">How it all comes together</h3>
<p>This is just scratching the surface of the topic of <em>state management</em> in Compose. For those willing to learn more, I will leave a link to the official <a target="_blank" href="https://developer.android.com/jetpack/compose/state">documentation</a>.</p>
<p>For now, however, let's see how our code looks with all the fixes:</p>
<pre><code><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">FollowTheBlog</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> isChecked <span class="hljs-keyword">by</span> remember { mutableStateOf(<span class="hljs-literal">false</span>) }

    Row(
        modifier = Modifier
            .border(
                width = <span class="hljs-number">1</span>.dp,
                color = Color.Gray,
                shape = RoundedCornerShape(<span class="hljs-number">5</span>.dp)
            )
            .padding(<span class="hljs-number">14</span>.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(<span class="hljs-string">"Check to follow the blog for awesome content!"</span>)
        Spacer(modifier = Modifier.width(<span class="hljs-number">8</span>.dp))
        Checkbox(
            checked = isChecked,
            onCheckedChange = { checked -&gt;
                isChecked = checked
                <span class="hljs-comment">// some follow the blog action</span>
            }
        )
    }
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625927005640/_FKv6je6G.gif" alt="ezgif.com-gif-maker.gif" /></p>
<p>And with that, we have a working checkbox!</p>
<h3 id="switching-to-jetpack-compose">Switching to Jetpack Compose</h3>
<p>Moving forward, Jetpack Compose will be a primary way to build UI on Android, and, sooner or later, the developers will have to embrace it.</p>
<p>To make things easier, here are some things to keep in mind when switching to Jetpack Compose:</p>
<h4 id="you-have-to-use-kotlin-to-utilize-jetpack-compose-fully">You have to use Kotlin to utilize Jetpack Compose fully.</h4>
<p>Compose is written in Kotlin, so its <a target="_blank" href="https://stackoverflow.com/questions/66433437/can-i-write-jetpack-compose-components-in-java">Java compatibility</a> is limited, and there are no plans to support it in the future. Therefore, if you haven't already, this might be a good point to start learning Kotlin. The good news is that Kotlin is awesome, and for Java developers, it shouldn't take more than a couple of weeks to start developing in Kotlin comfortably.</p>
<h4 id="jetpack-compose-is-fully-compatible-with-the-old-xmlview-based-way-of-building-ui">Jetpack Compose is fully compatible with the old <code>.XML</code>/<code>View</code>-based way of building UI.</h4>
<p>You can start migrating your project to Compose on a screen-by-screen basis, or even <em>add Compose components to existing <code>.XML</code> layouts or <code>ViewGroups</code></em>. You can do it with a <code>ComposeView</code>, which you can use as a regular <code>View</code>. It has a <code>setContent { }</code> function that allows you to add composables to existing UI.</p>
<pre><code><span class="hljs-selector-tag">composeView</span><span class="hljs-selector-class">.setContent</span> {
    <span class="hljs-comment">// you can use composables here, </span>
    <span class="hljs-comment">// which will be added to the view</span>
    <span class="hljs-selector-tag">Text</span>(text = <span class="hljs-string">"I am Compose inside this View!"</span>)
}
</code></pre><p>It also works great the other way around. <em>You can use regular <code>Views</code> or layouts inside the Composable scope.</em> For that, you can use a composable function <code>AndroidView</code>, which has a factory that provides a <code>context</code> and allows you to inflate <code>Views</code> or layouts.</p>
<pre><code>setContent {
    AndroidView(
        factory = { context -&gt;
            // use this context <span class="hljs-keyword">to</span> inflate views <span class="hljs-keyword">or</span> layouts
            TextView(context).apply {
                <span class="hljs-type">text</span> = "I am a View inside Compose!"
            }
        }
    )
}
</code></pre><p>You can find more information on interoperability API in the official <a target="_blank" href="https://developer.android.com/jetpack/compose/interop/interop-apis">documentation</a>.</p>
<h4 id="jetpack-compose-can-be-easily-integrated-with-common-android-libraries-and-popular-stream-based-solutions">Jetpack Compose can be easily integrated with common Android libraries and popular stream-based solutions</h4>
<p>Compose comes with support for ViewModels, Navigation, Paging, as well as other Android libraries. It also provides an API to listen to <code>LiveData</code>, <code>Flow</code> or RxJava's <code>Observable</code> and represent their values as <code>State</code>.</p>
<p>This makes integrating Compose into an existing project much easier, especially if the project has an architecture with a <a target="_blank" href="https://developer.android.com/jetpack/compose/architecture">unidirectional data flow</a>.</p>
<p>As always, there is a lot of useful information about that in the <a target="_blank" href="https://developer.android.com/jetpack/compose/libraries">documentation</a>.</p>
<h4 id="some-other-things-to-keep-in-mind">Some other things to keep in mind</h4>
<ul>
<li><p>To start using Jetpack Compose, you need at least the Arctic Fox version of Android Studio, which as of the time of writing is available in <a target="_blank" href="https://developer.android.com/studio/preview">Beta</a>. </p>
</li>
<li><p>Most people will probably start using Compose in an existing project. While adding Compose to an existing project shouldn't be too hard, depending on the state of your dependencies (pun not intended), it can be a bumpy ride. To make things easier, please refer to this <a target="_blank" href="https://developer.android.com/jetpack/compose/setup#add-compose">guide</a> and be sure to <em>upgrade the Gradle plugin to the latest version</em>.</p>
</li>
</ul>
<ul>
<li><p>At the time of this writing, the Compose Compiler requires Kotlin version <code>1.4.32</code>. If you are using <code>1.5</code> features in your project, you might have to wait a bit or use the <a target="_blank" href="https://stackoverflow.com/questions/65545018/where-can-i-put-the-suppresskotlinversioncompatibilitycheck-flag">suppressKotlinVersionCompatibilityCheck</a> flag, which might cause unexpected behavior.</p>
</li>
<li><p>Compose allows you to preview your UI without building your app, which greatly speeds up development. You can also <em>interact with the preview</em> as you would on a normal device. However, depending on your version of Android Studio, this feature might be experimental and therefore hidden. To turn in on, go to <code>Preferences -&gt; Experimental -&gt; Enable interactive and animation preview tools</code>.</p>
</li>
</ul>
<ul>
<li>For many of us who are using <code>ConstraintLayout</code> on a daily version, Compose has its  <a target="_blank" href="https://developer.android.com/jetpack/compose/layouts/constraintlayout">own version</a>. <code>MotionLayout</code> is not supported just yet, but the Compose team is working on supporting it.</li>
</ul>
<h3 id="conclusion">Conclusion</h3>
<p>Jetpack Compose is a huge toolkit, and one can probably write a whole book about it. It makes writing beautiful UI much easier and offers quite a few APIs and features that allow us to build UI in ways that weren't possible with layouts and views.</p>
<p>Compose has already hit a release candidate version and will be available as a stable version in no time. As I have noted before, this will be a new standard for Android development. Therefore, <em>now is as good a time as any to start learning it</em>.</p>
<p>I am truly excited about this new chapter in Android development and the journey that lies ahead. Hopefully, for some people, this post will make starting this journey a little bit easier.</p>
<p>See you next time.</p>
<p><em>To starting new journeys,</em></p>
<p><em>Max.</em></p>
]]></content:encoded></item><item><title><![CDATA[7 Tips for Becoming a Better Developer]]></title><description><![CDATA[Most of the writing on software development is very technical, aimed at researching and solving a particular problem. Such writing provides tremendous value, and I imagine most of what I will write in this blog will be just that - posts focusing on t...]]></description><link>https://maxkim.dev/7-tips-for-becoming-a-better-developer</link><guid isPermaLink="true">https://maxkim.dev/7-tips-for-becoming-a-better-developer</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[tips]]></category><category><![CDATA[Developer Blogging]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Max Kim]]></dc:creator><pubDate>Mon, 05 Jul 2021 19:12:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1625249464285/cRejdKYNs.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most of the writing on software development is very technical, aimed at researching and solving a particular problem. Such writing provides tremendous value, and I imagine most of what I will write in this blog will be just that - posts focusing on technical aspects of certain languages, platforms, and frameworks.</p>
<p>For this first entry, however, I would like to take a look at the bigger picture and think about the main things that helped me a lot in becoming a better developer in the past couple of years.</p>
<p>Most of the examples in this blog post are related to Android development. Still, the concepts are applicable to any field.</p>
<h2 id="tip-1-know-your-domain">Tip #1: Know your domain</h2>
<p>If you have chosen something as your craft, and are spending most of your waking hours doing it, it would only make sense to always improve and hone that skill.</p>
<p>Regardless of your current experience, never stop learning. Don't ever make a mistake and assume that you know something already and there is nothing to learn. Even the basics. By doing that, you shut your brain off to any possibility of learning something new, and <em>there is always something to learn</em>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625250231450/Jk5hMrWDD.jpeg" alt="agence-olloweb-d9ILr-dbEdg-unsplash.jpg" /></p>
<p>Remain curious, be open-minded, and always ask questions. Never be content with things you don't know. Never settle with what you do know. Especially when it comes to your area of expertise.</p>
<blockquote>
<p>“Sell your cleverness and buy bewilderment.” - Rumi</p>
</blockquote>
<p><strong>Here are some things</strong> that have helped me a lot to become a better Android developer. The principles, however, apply to any language and platform.</p>
<ul>
<li><em>Start searching for answers in the source code and the documentation</em>. By reading the source code of Kotlin and Android, I got many great ideas that I now regularly use in my projects, and it helped a lot to improve my style as well. </li>
</ul>
<ul>
<li><em>Strive to fully understand things that you use on a daily basis.</em> If you are an Android developer like me, start with Activities and Fragments, you will use them in every single application. Open up the source for <code>AppCompatActivity</code> and go through all the public methods it exposes. Look for things you never knew existed. Do the same for <code>Fragment</code>. Modern IDEs make it so easy and you will learn a lot. Make a habit of  <code>CMD/Ctrl</code> + clicking classes and see what’s inside.</li>
</ul>
<ul>
<li><em>Stay informed about new things in your domain.</em> Find a newsletter, read blogs, watch YouTube - do anything to stay in touch with what is happening in your chosen field.</li>
</ul>
<h2 id="tip-2-know-your-tools">Tip #2: Know your tools</h2>
<p>Every craftsman has to constantly improve their knowledge of the tools they use. If your main line of work is being a developer, I imagine you spend a lot of time in some kind of text editor, or, most probably an IDE. Nowadays, IDEs are very advanced and it’s highly likely you don't know most of the features your IDE offers. Some of the features might not be useful to you personally, but you won't know it if you don't even suspect they exist.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625250479501/yf_Jo0LJQ.jpeg" alt="natalino-d-amato-sRVZXTNnLX4-unsplash.jpg" /></p>
<p><strong>Here are some things to get you started:</strong></p>
<ul>
<li>Google and try out different productivity tips for your IDE.</li>
</ul>
<ul>
<li>Learn and use the shortcuts for actions you are using repetitively.</li>
</ul>
<ul>
<li>See if there is a template/snippet functionality in your IDE.</li>
</ul>
<ul>
<li>Invest some time in setting up custom lint rules to quickly spot errors and code smells.</li>
</ul>
<ul>
<li>Browse available plugins and see if any can help improve your workflow.</li>
</ul>
<p>Apart from the IDE/text editor, make sure to spend some time looking into features and productivity tips for your Mac/PC, whatever you use. It is your main tool when it comes to coding, so make sure you are comfortable with it.</p>
<p>There should not be a single thing that is detrimental to your workflow and the quality of your work. If there is, someone online has probably found a solution. <em>Go find it.</em></p>
<h2 id="tip-3-sharpen-your-micro-and-macro">Tip #3: Sharpen your micro and macro</h2>
<p>There are two concepts you have probably heard of, being a developer - <em>Clean Code</em> and <em>Clean Architecture</em>. I like to refer to them as micro and macro.</p>
<p><em>Clean Code</em> is your micro - how you write your code, the naming conventions, the style/conventions of your language of choice, the structure of your functions, DSL, etc.</p>
<p><em>Clean Architecture</em> is your macro - the architecture of your software, the way you structure your files, and what public APIs you expose.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625251440557/HdGN6VZ8v.jpeg" alt="daniele-levis-pelusi-4mpsEm3EGak-unsplash.jpg" /></p>
<p>When it comes to the Clean Code, or your micro, there are a lot of things you can do to improve it, but if you don't know where to start, I would recommend Robert. C. Martin's book Clean Code, which popularized the concept. Or just google it, there is a lot of material on the topic. The main point here is that your code should make sense and be easily readable by your fellow developers. Or by you after a year or so.</p>
<p>The Clean Architecture is a harder nut to crack, especially if you are just starting out. For the beginners out there I would recommend focusing on learning Clean Code and the specifics of your language/platform. As soon as you get a grasp of that, learn the most popular architectural pattern for your platform. In the case of Android, it would be MVVM. After that, learn the Clean Architecture, which also has an excellent corresponding book by Robert. C. Martin.</p>
<p>Moreover, all architectural patterns aim to solve certain problems, they have evolved over time and became what they are for a reason. Make sure you know and understand what those problems are, and don't blindly copy the patterns just to use them. It would certainly be better than not using any pattern at all, however, the main point I am trying to make here is if you are doing something, understand the <em>why</em> behind it. </p>
<p>Some would say that in smaller projects it doesn't make sense to complicate the codebase with the boilerplate that might come from implementing a Clean Architecture pattern or any other pattern for that matter, and I would argue that <em>how you do anything is how you do everything</em>. Your attitude towards your work is a habit and it can only go two ways. </p>
<h2 id="tip-4-writers-are-readers">Tip #4: Writers are readers</h2>
<p>I love books and I am fascinated by the people who write them. Many, if not all, of the most accomplished writers, are first and foremost readers themselves - because of their love for the craft but also to <em>fuel their creativity</em>.</p>
<p>I don't see why it should be any different for writing code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625252995870/PepZEqWOg.jpeg" alt="markus-spiske-cvBBO4PzWPg-unsplash.jpg" /></p>
<p>There are a lot of <strong>open-source projects that you can learn from</strong>. Tutorials and documentation are often good for learning isolated cases. By reading real projects, you learn how it all comes together. It is one of the best ways to learn both macro and micro. So do yourself a favor and let GitHub <em>become your library</em>.</p>
<p>If a project's author is better than you, you will learn a lot. And if, on the other hand, you happen to be further along on this journey, you can train your brain to spot things that can be improved. You should be doing it with your own code anyway. It is <em>a win-win situation</em>.</p>
<p>And if you don't understand or don't agree with something you see, don't dismiss it immediately. Think about it and understand it. Talk with other people about code. Discuss ideas. <em>Always question your logic</em>. We are creatures of habit, but for many people, unfortunately, habits mean living in the past, repeating engrained neurological patterns again and again without any potential for growth. Just as life can get stale and uneventful because of routine, your code can and will get stale without active and mindful participation.</p>
<p>Here is an  <a target="_blank" href="https://github.com/binaryshrey/Awesome-Android-Open-Source-Projects">awesome curated list</a> for all you Android developers to get you started.</p>
<p>And if you are not an Android developer, you know  <a target="_blank" href="https://www.google.com">what to do</a>.</p>
<h2 id="tip-5-do-not-ever-sacrifice-the-quality-of-your-code">Tip #5: Do not ever sacrifice the quality of your code</h2>
<p>In science, there is a concept called <em>entropy</em> - a measure of disorder in a given system. Or in layman's terms - as time goes on, things tend to fall apart. Everything that is orderly, will always tend towards disorder.</p>
<p><em>Code is no different</em>. </p>
<p>There are many reasons why code will degrade over time and turn into an unmanageable pile of spaghetti on some occasions. It might be a result of poor planning, it might happen because of some shortcuts we continuously take during development, it might happen because of time constraints, it might happen because we lose passion for a project and abandon things at a “good enough” state.</p>
<p>Never stop at the point when your code works. Try to see how you can improve the structure of your code, how you can make your code more readable and elegant. It might sound like a lot of work in the beginning but, eventually, your first drafts will start coming out very close to the final result.</p>
<p>If you had finished your coding session late at night, make a habit of reviewing it in the morning, and see if you still like what you wrote and things make sense.</p>
<p><strong>Avoid taking shortcuts.</strong></p>
<p>When a thought creeps in to make it a little bit easier for yourself, sacrificing the code quality in the process, catch that thought immediately and make it a trigger for yourself to <em>step up your game</em>.</p>
<p>There will be times when you will be pressured by time and will have to find solutions fast. Never see it as an excuse for sloppy code. See it as a challenge and a test for everything you have learned so far. Train yourself to maintain a professional approach to your work and never drop your standards, especially when things are falling apart around you.</p>
<p>And just to make things clear - I do not ask you to write perfect code.</p>
<p><em>I ask you not to write code that is worse than what you are capable of. </em></p>
<h2 id="tip-6-be-active-and-engaged-at-what-you-do">Tip #6: Be active and engaged at what you do</h2>
<p>One of my main passions in life is learning how to learn. Trust me, this simple skill is a game-changer for anything you do in life. I love learning and constant growth, and for that reason, I have a major beef with schools and our outdated education system. Don't worry, I will not go on a huge tangent about that, but there is a reason I mentioned schools here.</p>
<p>From a young age, school taught us to sit still, passively absorb information, and expect others to have all the answers.</p>
<p><em>That is not how learning works.</em></p>
<p>One of the most important components of learning is being <em>active</em> and <em>engaged</em>, just like you had been learning before you went to elementary.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625255706942/lWWm_URh_.jpeg" alt="azamat-e-FP_N_InBPdg-unsplash.jpg" /></p>
<p>The same applies to writing code. When you are actively thinking and are engaged in the process, you will make fewer mistakes, write better code, and every coding session will become a learning session as well.</p>
<p>Let's talk about every developer's best friend for a minute. Yes, StackOverflow. Without any doubt, it is one of the most valuable resources for any developer. However, if you are more advanced and looking for ways to improve, I want you to pay attention to how you use it.</p>
<p>Many developers become too dependant on StackOverflow. They expect it to have all the answers to every question they might have during the development process. </p>
<p>You can certainly copy-paste other people's code, and it might be the best piece of code for your problem. There is nothing wrong with that. All I ask you is this - <em>actively think</em> and <em>digest that code</em> while you are at it.</p>
<p><strong>Understand the code and make it your own.</strong></p>
<p>And before we move on, just as a thought experiment ask yourself one simple question. If, as an exercise, you were not allowed to use StackOverflow for one day, and had to search for solutions on your own, in the documentation and the source code, would it make you a better developer?</p>
<h2 id="tip-7-take-care-of-your-body">Tip #7: Take care of your body</h2>
<p>And here is the topic I wish got discussed more often in our community. First things first. I am not a nutrition or fitness expert but I feel like this needs to be mentioned here. Sometimes we get too involved in certain areas of our life, often times our career, while forgetting the others. But I would argue that there is nothing more important than our well-being. Especially for us, programmers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625255069012/qEg2XmfnR.jpeg" alt="gabin-vallet-J154nEkpzlQ-unsplash.jpg" /></p>
<p>I don't want to beat a dead horse here. We all know and heard a thousand times how bad it is to sit in front of a computer all day, eating pizza, and ignoring sunshine. Much fewer of us have an <em>established routine to make ourselves healthier</em>.</p>
<p>It all comes to priorities. Doing things without seeing an immediate benefit is incredibly hard, especially if the alternative is more satisfying, or doesn't require effort. I can name many reasons why being healthy will benefit your career as a software developer. For one, everyone knows the difference between a foggy slow brain, starved of nutrients and oxygen, and a well-rested brain fueled by proper nutrition. </p>
<p>However, I feel like there are many <em>more important reasons</em> than programming, or any career for that matter, why you should consider <em>shining some consciousness</em> onto the health and fitness area of your life and establishing a health-focused routine that will serve you for years to come. Becoming a better software developer will come as a bonus.</p>
<p>Here are some of my reasons:</p>
<ul>
<li><p>I want to have a healthy body and energy to have many adventures and maximize my life experiences in every way, for as long as I can.</p>
</li>
<li><p>I want to be the best lover for my partner.</p>
</li>
<li><p>I want to set an example for my future children of what it means to be a self-responsible, conscious human being.</p>
</li>
</ul>
<p><em>Find your reasons and make sure they will drive you.</em></p>
<h2 id="bonus-tip-8-improve-the-interface">Bonus Tip #8: Improve the interface</h2>
<p>With all the heavy hitters out of the way, here is a small bonus one, that helped me a lot in the past couple of months. I have been using computers since childhood, learning how to use one as I went along. As a result, I developed some less than optimal habits.</p>
<p>As we have discussed earlier, we should always learn how to use our tools more efficiently. However, there is one more thing that stands in the way between our thoughts and the final code in the IDE - the interface between yourself and your computer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625254765409/-f6UEa7XL.jpeg" alt="melanie-deziel-g1CDLIh3Cx4-unsplash.jpg" /></p>
<p>Or <em>your hands</em>, for less technical folk out there.</p>
<p>It shouldn't be a surprise that your typing speed will impact your coding speed. However, there is one more benefit for typing faster. </p>
<p>Our brains are incredibly complicated biological machines, designed to process a huge amount of data. And when you force it to slow down, it will eventually become bored, disengage, and your thoughts will wander somewhere else. Just imagine reading a book one word at a time, with pauses in between.</p>
<p>On the other hand, when your hands are capable of putting information into your computer much faster, you will be able to concentrate on your code and more reliably achieve the flow state. You will not be distracted by typos and huge pauses needed for typing out the code. Imagine a master pianist. How good would their music be, if they had to focus on where to put their fingers?</p>
<p>So speaking of my childhood typing habits, I have recently noticed that my right hand is very passive while typing, and my fingers are very chaotic. So I started googling the correct typing techniques and found this incredible website https://www.typing.com/ to help me out.</p>
<p>After just a couple of months of training, my development speed improved a lot, so maybe it will also help you. It has a free version and I am not affiliated with them in any way.</p>
<p>And by the way, your brain will thank you for learning something new.</p>
<h3 id="before-we-part-our-ways">Before we part our ways...</h3>
<p>... there is a last piece of advice I want to give you, especially, if you are just starting out as a developer. If the amount of information feels overwhelming, in this post or anywhere else on the web, don't sweat it. And don't even try to implement everything at once. Pick something, one small thing, and see if it works for you. And keep adding to it as time goes on. Remember - <em>little by little, a little becomes a lot</em>.</p>
<p>The main point is not to memorize these tips or perfect everything I talk about here. The main point is <strong>to constantly try out new things and see if they benefit you in any way</strong>. The above-mentioned tips are those that stuck with me and helped me tremendously. </p>
<p><em>Be curious and experiment.</em></p>
<p>See you next time.</p>
<p>To growth, and learning,</p>
<p><em>Max</em></p>
]]></content:encoded></item></channel></rss>