<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Kotlin - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Kotlin - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 09 Oct 2026 09:33:16 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/kotlin/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Learn Modern Kotlin ]]>
                </title>
                <description>
                    <![CDATA[ We just published a comprehensive, free Kotlin course on the freeCodeCamp.org YouTube channel. Whether you're targeting Android development, scalable backend services, or cross-platform applications,  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-modern-kotlin/</link>
                <guid isPermaLink="false">6abfcc8e01291b49f46e78ac</guid>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 02 Oct 2026 15:23:58 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5f68e7df6dfc523d0a894e7c/bc8218cc-11c7-469e-b549-e9944e187099.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We just published a comprehensive, free Kotlin course on the freeCodeCamp.org YouTube channel.</p>
<p>Whether you're targeting Android development, scalable backend services, or cross-platform applications, this course takes you from writing your first line of code to mastering asynchronous programming and reactive streams.</p>
<p>Here are the things covered in this course:</p>
<ul>
<li><p><strong>Fundamentals &amp; Setup</strong><br>Installing IntelliJ IDEA, understanding the JVM, type inference, primitive types, control flow (<code>when</code>, loops), and Kotlin’s built-in <strong>null safety</strong>.</p>
</li>
<li><p><strong>Functions &amp; Collections</strong><br>Default arguments, <code>vararg</code>, lambda functions, arrays, collections (<code>List</code>, <code>Set</code>, <code>Map</code>), binary search, and error handling.</p>
</li>
<li><p><strong>Modern OOP</strong><br>Primary/secondary constructors, <code>init</code> blocks, <code>data</code> classes, <code>sealed</code> classes, companion objects, singletons, delegation, and <strong>extension functions</strong>.</p>
</li>
<li><p><strong>Deep-Dive Generics</strong><br>Variance (<code>in</code>/<code>out</code>), upper bounds, the <code>where</code> clause, and working around JVM type erasure using <code>reified</code> type parameters.</p>
</li>
<li><p><strong>Coroutines</strong><br>Non-blocking asynchronous programming using <code>launch</code>, <code>async</code>, <code>runBlocking</code>, structured concurrency, timeouts, cancellations, and <code>withContext</code>.</p>
</li>
<li><p><strong>Kotlin Flows &amp; Reactive Streams</strong><br>Cold streams, intermediate and terminal operators (<code>launchIn</code>, <code>asLiveData</code>), exception transparency, <code>retry</code> logic, and lifecycle handling.</p>
</li>
</ul>
<p>The course is completely free and available now <a href="https://www.youtube.com/watch?v=nqK3oJ682mQ">on the freeCodeCamp.org YouTube channel</a> (10-hour watch).</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/nqK3oJ682mQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Accessible Android Apps with Jetpack Compose: A Comprehensive Guide ]]>
                </title>
                <description>
                    <![CDATA[ Making your mobile apps accessible makes sure that everyone, including people with visual, auditory, motor, or cognitive disabilities, can interact with and navigate the app effectively. Historically, ]]>
                </description>
                <link>https://www.freecodecamp.org/news/accessibility-in-jetpack-compose-comprehensive-tutorial/</link>
                <guid isPermaLink="false">6a96f33812e0a826683b9f0f</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jetpack Compose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vamsi Vaddavalli ]]>
                </dc:creator>
                <pubDate>Tue, 01 Sep 2026 15:46:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/b89c199c-9ec0-48f2-b7ff-193c5b16a1d4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Making your mobile apps accessible makes sure that everyone, including people with visual, auditory, motor, or cognitive disabilities, can interact with and navigate the app effectively.</p>
<p>Historically, accessibility has often been treated as an afterthought. Something to consider only if time permitted before a release.</p>
<p>Today, that perspective has fundamentally changed. With regulations like the European Accessibility Act (EAA) taking effect across European Union markets, building accessible software is increasingly a legal and business requirement.</p>
<p>More importantly, building accessible applications is just good engineering. Accessible apps improve usability for all users and help make sure that you're not excluding a substantial portion of your potential audience.</p>
<p>Jetpack Compose simplifies accessibility compared to the traditional Android View system. Because Compose is declarative and state-driven, it manages semantic metadata alongside your visual user interface.</p>
<p>In this comprehensive guide, you will learn how accessibility works in Jetpack Compose, how to use the Semantics tree, how to apply essential and advanced accessibility patterns, and how to thoroughly test your apps using automated tests, Google's Accessibility Scanner, Android Studio's Layout Inspector, and TalkBack.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this guide, you'll need:</p>
<ul>
<li><p>Basic familiarity with Kotlin and Jetpack Compose (such as Composables, Modifiers, and State).</p>
</li>
<li><p>Android Studio (Hedgehog, Iguana, Jellyfish, Koala, Ladybug, or newer).</p>
</li>
<li><p>An Android device or emulator running Android 9.0 (API 28) or higher with access to the Google Play Store (to install and run the current version of Google Accessibility Scanner).</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-why-accessibility-matters-in-modern-android-development">Why Accessibility Matters in Modern Android Development</a></p>
</li>
<li><p><a href="#heading-core-concepts-of-android-accessibility">Core Concepts of Android Accessibility</a></p>
</li>
<li><p><a href="#heading-semantics-in-jetpack-compose">Semantics in Jetpack Compose</a></p>
</li>
<li><p><a href="#heading-essential-accessibility-practices">Essential Accessibility Practices</a></p>
</li>
<li><p><a href="#heading-advanced-accessibility-techniques">Advanced Accessibility Techniques</a></p>
</li>
<li><p><a href="#heading-how-to-test-and-debug-accessibility">How to Test and Debug Accessibility</a></p>
</li>
<li><p><a href="#heading-real-world-accessible-ui-patterns">Real-World Accessible UI Patterns</a></p>
</li>
<li><p><a href="#heading-accessibility-audit-checklist">Accessibility Audit Checklist</a></p>
</li>
<li><p><a href="#heading-conclusion-and-next-steps">Conclusion and Next Steps</a></p>
</li>
<li><p><a href="#heading-essential-resources">Essential Resources</a></p>
</li>
</ul>
<h2 id="heading-why-accessibility-matters-in-modern-android-development">Why Accessibility Matters in Modern Android Development</h2>
<p>According to the World Health Organization (WHO), more than 1.3 billion people (representing roughly 16% of the global population) live with a significant disability. This includes people with permanent visual impairments, hearing loss, physical motor limitations, and cognitive or neurological differences.</p>
<p>In addition to permanent disabilities, users can often experience temporary or situational limitations. A person holding a baby with one hand has temporary motor constraints. Someone using their phone in harsh midday sunlight experiences situational visual impairment. And someone in a loud airport terminal experiences situational hearing limitations.</p>
<p>Designing an accessible app ensures that your interface remains resilient and usable across all of these scenarios and more.</p>
<p>Beyond empathy and inclusive design, accessibility is increasingly governed by international law.</p>
<p>In the European Union, the <strong>European Accessibility Act (EAA)</strong> mandates accessibility for a defined list of products and services, including smartphones and computers, e-commerce, consumer banking services, e-books, and passenger transport services. In practice, conformity is typically demonstrated against <strong>EN 301 549</strong>, the European accessibility standard for digital products and services.</p>
<p>In the United States, the <strong>Americans with Disabilities Act (ADA)</strong> applies to state and local governments (Title II, which, since 2024, has an explicit web and mobile app rule requiring compliance with WCAG 2.1 Level AA) and to public accommodations (Title III). Separately, <strong>Section 508</strong> of the Rehabilitation Act requires federal agencies' information and communications technology to be accessible.</p>
<p>Failing to meet these standards can result in legal penalties and brand damage. Conversely, prioritizing accessibility expands your total addressable market and boosts user retention.</p>
<p>Quality also affects distribution: Google's Android vitals documentation notes that a high user-perceived crash rate hurts your app's discoverability on Google Play.</p>
<h2 id="heading-core-concepts-of-android-accessibility">Core Concepts of Android Accessibility</h2>
<p>To design accessible applications in Jetpack Compose, you must understand how the underlying Android operating system communicates with assistive technologies.</p>
<h3 id="heading-understanding-android-accessibility-services">Understanding Android Accessibility Services</h3>
<p>Android includes several built-in accessibility services that run as background processes. These services intercept the app's user interface and translate it into alternative sensory feedback or alternative input mechanisms:</p>
<ul>
<li><p><strong>TalkBack (Screen Reader):</strong> TalkBack is Android's built-in screen reader designed for blind and low-vision users. It inspects your interface elements, converts visual content and semantic descriptions into synthesized speech and haptic vibrations, and enables non-visual navigation using linear swipe gestures.</p>
</li>
<li><p><strong>Switch Access:</strong> Designed for users with severe motor impairments who can't use a physical touch screen, Switch Access allows users to control their device using one or more physical switches (such as foot pedals, sip-and-puff devices, or single buttons) or a connected keyboard. It scans through focusable screen elements sequentially, allowing the user to select items when highlighted.</p>
</li>
<li><p><strong>Voice Access:</strong> Allows users to control their entire phone using spoken commands (such as "Tap Open," "Scroll down," or "Type hello"). It assigns numeric badges to interactive elements based on their accessibility labels so users can trigger actions by number.</p>
</li>
<li><p><strong>Select to Speak:</strong> Allows users to highlight specific paragraphs, buttons, or icons on the screen to hear them spoken aloud without turning on full TalkBack navigation.</p>
</li>
</ul>
<p>All of these accessibility services share one common requirement: they don't interact directly with visual pixels. Instead, they read the <strong>Semantics Tree</strong> generated by your application.</p>
<h3 id="heading-how-the-compose-semantics-tree-works">How the Compose Semantics Tree Works</h3>
<p>When you build a user interface in Jetpack Compose, Compose generates two separate but linked internal tree structures:</p>
<ol>
<li><p><strong>The Layout (UI) Tree:</strong> This tree contains the visual rendering nodes that measure, place, and draw pixels on the screen (such as Canvas, Box, Row, Column, Text, and Image).</p>
</li>
<li><p><strong>The Semantics Tree:</strong> This tree runs in parallel with the Layout tree. It contains metadata that describes the meaning, purpose, state, and interactive capabilities of each element.</p>
</li>
</ol>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Visual Layout Tree (UI &amp; Pixels)</th>
<th>Semantics Tree (Accessibility &amp; TalkBack)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Container</strong></td>
<td><code>Row(modifier = Modifier.clickable { ... })</code></td>
<td><strong>Single Merged Accessibility Node</strong></td>
</tr>
<tr>
<td><strong>Child 1</strong></td>
<td><code>Image(Icons.Default.Star)</code></td>
<td><em>Merged into parent description</em></td>
</tr>
<tr>
<td><strong>Child 2</strong></td>
<td><code>Text("4.5")</code></td>
<td><em>Merged into parent description</em></td>
</tr>
<tr>
<td><strong>Child 3</strong></td>
<td><code>Text("Rating")</code></td>
<td><em>Merged into parent description</em></td>
</tr>
<tr>
<td><strong>Result</strong></td>
<td>Renders separate visual pixels on screen</td>
<td><strong>TalkBack announces:</strong> <em>"Rating: 4.5 stars, button"</em></td>
</tr>
</tbody></table>
<p>Standard Material Compose components (such as <code>Button</code>, <code>Checkbox</code>, <code>Slider</code>, <code>Switch</code>, and <code>Text</code>) automatically populate appropriate semantic properties into the Semantics tree. For example, a <code>Button</code> composable automatically sets its role to <code>Role.Button</code> and attaches a click action.</p>
<p>But when you build custom layouts, canvas drawings, or non-standard interactive widgets, Compose can't automatically infer your design intent. In those cases, you must use Compose's semantic modifiers to enrich the Semantics tree manually.</p>
<h3 id="heading-the-wcag-21-pour-principles">The WCAG 2.1 POUR Principles</h3>
<p>The international benchmark for digital accessibility is the <strong>Web Content Accessibility Guidelines (WCAG) 2.1</strong>, published by the World Wide Web Consortium (W3C). These guidelines are organized around four core principles known by the acronym <strong>POUR</strong>:</p>
<ul>
<li><p><strong>Perceivable:</strong> Information and UI components must be presentable to users in ways they can perceive. Content can't be invisible to all of a user's senses. In Android apps, this means providing descriptive text alternatives for all visual media, supporting dynamic font scaling, and maintaining high color contrast.</p>
</li>
<li><p><strong>Operable:</strong> User interface components and navigation must be operable. Users must be able to perform all interactions regardless of whether they use a touchscreen, a hardware keyboard, voice commands, or a switch device. This requires adequate touch targets (Android's guideline is at least 48dp × 48dp) and logical navigation orders.</p>
</li>
<li><p><strong>Understandable:</strong> Users must be able to understand both the information and the interface's operation. This means writing clear labels, providing meaningful validation error messages, avoiding sudden unexpected layout shifts, and structuring forms predictably.</p>
</li>
<li><p><strong>Robust:</strong> Content must be sufficiently robust to be reliably interpreted by a wide variety of user agents and assistive technologies. In Compose, this means avoiding hacky workarounds, using standard semantic roles, and honoring system-level user preferences.</p>
</li>
</ul>
<h2 id="heading-semantics-in-jetpack-compose">Semantics in Jetpack Compose</h2>
<p>In this section, we'll examine how Compose exposes and manipulates semantic metadata.</p>
<h3 id="heading-what-are-semantics">What Are Semantics?</h3>
<p>Semantics in Jetpack Compose are key-value properties attached to layout nodes using the <code>Modifier.semantics</code> modifier. They convey information such as:</p>
<ul>
<li><p>What an element is called (<code>contentDescription</code>)</p>
</li>
<li><p>What kind of UI control it represents (<code>role = Role.Checkbox</code>, <code>Role.Button</code>, <code>Role.Tab</code>)</p>
</li>
<li><p>What state it currently holds (<code>stateDescription = "Checked"</code>, <code>progressBarRangeInfo</code>)</p>
</li>
<li><p>What actions the user can perform (<code>onClick</code>, <code>onLongClick</code>, <code>customActions</code>)</p>
</li>
</ul>
<h3 id="heading-basic-semantic-properties-and-content-descriptions">Basic Semantic Properties and Content Descriptions</h3>
<p>The most widely used semantic property is <code>contentDescription</code>. It provides a localized textual representation of non-textual UI elements, such as icons, photographs, and vector graphics.</p>
<p>Here's how you provide content descriptions for visual components:</p>
<pre><code class="language-kotlin">// A functional icon button that performs an action
IconButton(onClick = { /* Open camera */ }) {
    Icon(
        painter = painterResource(id = R.drawable.ic_camera),
        contentDescription = "Open camera"
    )
}

// A decorative background illustration
Image(
    painter = painterResource(id = R.drawable.decorative_pattern),
    contentDescription = null, // Informs TalkBack to skip this node completely
    modifier = Modifier.fillMaxWidth()
)
</code></pre>
<h4 id="heading-how-it-works-under-the-hood">How It Works Under the Hood</h4>
<p>When TalkBack navigates to the <code>Icon</code>, it reads the <code>contentDescription</code> aloud (something like "Open camera, button, double tap to activate"). TalkBack automatically appends the word "button" because <code>IconButton</code> exposes <code>Role.Button</code>. (Exact TalkBack phrasing varies by version and locale. The spoken examples throughout this guide are illustrative.)</p>
<p>For decorative elements (such as subtle background shapes, divider lines, or visual illustrations that accompany adjacent descriptive text), you should explicitly set <code>contentDescription = null</code>. Setting <code>contentDescription = null</code> instructs Compose to omit that element from the Semantics tree, preventing screen readers from stopping on meaningless visual noise.</p>
<h3 id="heading-custom-semantics-and-state-descriptions">Custom Semantics and State Descriptions</h3>
<p>When an element changes its state dynamically (such as toggling between playing and paused, or expanded and collapsed), screen reader users need to be notified of the current state before they interact with it.</p>
<p>You can set <code>stateDescription</code> and <code>role</code> inside the <code>Modifier.semantics</code> block:</p>
<pre><code class="language-kotlin">var isPlaying by remember { mutableStateOf(false) }

IconButton(
    onClick = { isPlaying = !isPlaying },
    modifier = Modifier.semantics {
        // Explicitly declare what state the media player is in
        stateDescription = if (isPlaying) "Playing audio" else "Audio paused"
        role = Role.Button
    }
) {
    Icon(
        imageVector = if (isPlaying) Icons.Default.Pause else Icons.Default.PlayArrow,
        contentDescription = if (isPlaying) "Pause" else "Play"
    )
}
</code></pre>
<h4 id="heading-how-it-works-under-the-hood">How It Works Under the Hood</h4>
<p>Without <code>stateDescription</code>, TalkBack only reads the action ("Play, button"). The user has to guess whether the audio is currently playing or stopped.</p>
<p>By adding <code>stateDescription</code>, TalkBack announces: <em>"Playing audio, Pause, button, double-tap to toggle."</em> This gives the user immediate confirmation of the current state followed by the action that activating the control will perform.</p>
<h3 id="heading-how-to-merge-semantics-with-mergedescendants">How to Merge Semantics with mergeDescendants</h3>
<p>In complex layouts, multiple individual composables often combine to represent a single logical entity. For instance, a user profile row might contain an avatar image, a username, an online badge, and a timestamp.</p>
<p>By default, TalkBack will treat every child <code>Text</code> and <code>Image</code> node as an independent stop, forcing the user to swipe four or five times just to move past a single list item.</p>
<p>You can use <code>Modifier.semantics(mergeDescendants = true)</code> to combine all descendant nodes into a single, cohesive accessibility node:</p>
<pre><code class="language-kotlin">// Bad: TalkBack focuses three separate times: "Star icon", "4.5", "Customer rating"
Row(modifier = Modifier.clickable { /* Navigate to reviews */ }) {
    Icon(
        imageVector = Icons.Default.Star,
        contentDescription = "Star icon"
    )
    Text(text = "4.5")
    Text(text = "Customer rating")
}

// Good: Merged into one single stop: "Customer rating: 4.5 out of 5 stars, button"
Row(
    modifier = Modifier
        .clickable(onClickLabel = "View all reviews") { /* Navigate to reviews */ }
        .semantics(mergeDescendants = true) {
            contentDescription = "Customer rating: 4.5 out of 5 stars"
        }
) {
    Icon(
        imageVector = Icons.Default.Star,
        contentDescription = null // Suppressed because parent provides full description
    )
    Text(text = "4.5")
    Text(text = "Customer rating")
}
</code></pre>
<h4 id="heading-how-it-works-under-the-hood">How It Works Under the Hood</h4>
<p>When <code>mergeDescendants = true</code> is set, Compose collapses the accessibility boundaries of all child composables. Instead of generating multiple stops in the Semantics tree, Compose exposes a single node to the accessibility framework. TalkBack focuses the entire <code>Row</code> as a single bounding box and reads the parent's <code>contentDescription</code>.</p>
<h3 id="heading-how-to-clear-semantics-with-clearandsetsemantics">How to Clear Semantics with clearAndSetSemantics</h3>
<p>In certain situations, a standard composable may include default semantic behaviors that interfere with your intended accessibility experience.</p>
<p>The <code>Modifier.clearAndSetSemantics</code> modifier clears all semantic properties that would otherwise be inherited from child composables or default implementations, allowing you to define a clean, custom semantic definition:</p>
<pre><code class="language-kotlin">// A composite badge displaying notification count
Box(
    modifier = Modifier.clearAndSetSemantics {
        contentDescription = "3 unread messages"
        role = Role.Button
    }
) {
    Icon(
        imageVector = Icons.Default.Email,
        contentDescription = "Email icon" // Cleared and ignored
    )
    Text(text = "3") // Cleared and ignored
}
</code></pre>
<h4 id="heading-how-it-works-under-the-hood">How It Works Under the Hood</h4>
<p>Unlike <code>Modifier.semantics</code>, which <em>adds</em> or <em>overrides</em> specific keys, <code>clearAndSetSemantics</code> discards all existing keys generated by the composable subtree. In the example above, the separate "Email icon" and "3" text nodes are completely erased from the Semantics tree and replaced with the single announcement: <em>"3 unread messages, button."</em></p>
<h2 id="heading-essential-accessibility-practices">Essential Accessibility Practices</h2>
<p>Now we'll cover the core accessibility practices you should implement in your applications, along with explanations of why each practice matters.</p>
<h3 id="heading-how-to-write-meaningful-content-descriptions">How to Write Meaningful Content Descriptions</h3>
<p>A content description should concisely explain the <strong>purpose</strong> or <strong>action</strong> of an element rather than its visual appearance.</p>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">// Descriptive, action-oriented label
IconButton(onClick = { deleteDraft() }) {
    Icon(
        imageVector = Icons.Default.Delete,
        contentDescription = "Delete draft message"
    )
}

// Contextual weather information
Image(
    painter = painterResource(R.drawable.weather_sunny),
    contentDescription = "Current weather: Sunny, 75 degrees Fahrenheit"
)
</code></pre>
<p>The icon description tells the user exactly what will happen when they tap the button ("Delete draft message"). The weather image communicates the actual underlying data rather than describing the art style.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Avoid generic or redundant descriptions
IconButton(onClick = { deleteDraft() }) {
    Icon(
        imageVector = Icons.Default.Delete,
        contentDescription = "Trash can icon button" // Bad: includes visual style and element type
    )
}

// Avoid empty strings on interactive elements
IconButton(onClick = { openSettings() }) {
    Icon(
        imageVector = Icons.Default.Settings,
        contentDescription = "" // Bad: leaves the button with no accessible label
    )
}
</code></pre>
<p>Including words like "icon" or "button" is redundant because TalkBack already announces the component's role. Using an empty string (<code>""</code>) on an interactive element leaves TalkBack with nothing meaningful to announce (typically read out as an unlabeled button), giving screen reader users zero context about what the button does. Compose's accessibility checks treat an empty content description the same as a missing one.</p>
<h3 id="heading-how-to-ensure-minimum-touch-target-sizes">How to Ensure Minimum Touch Target Sizes</h3>
<p>Google's Material Design and Android accessibility guidelines require all interactive elements to have a minimum touch target size of at least <strong>48dp × 48dp</strong>, which corresponds to a physical size of about 9mm. This is squarely within the 7–10mm range Google recommends for touchscreen targets.</p>
<p>For comparison, WCAG itself sets lower web-oriented baselines: WCAG 2.1 Success Criterion 2.5.5 requires 44×44 CSS pixels at Level AAA, and WCAG 2.2 Success Criterion 2.5.8 requires 24×24 CSS pixels at Level AA. The 48dp rule is Android's stricter platform standard.</p>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">// Method A: Using minimumInteractiveComponentSize()
Box(
    modifier = Modifier
        .minimumInteractiveComponentSize() // Expands touch area to 48dp x 48dp
        .clickable { /* Toggle bookmark */ }
) {
    Icon(
        imageVector = Icons.Default.Bookmark,
        contentDescription = "Bookmark article",
        modifier = Modifier.size(24.dp) // Visual size is 24dp, touch target is 48dp
    )
}

// Method B: Standard IconButton (built-in 48dp target)
IconButton(onClick = { /* Toggle bookmark */ }) {
    Icon(
        imageVector = Icons.Default.Bookmark,
        contentDescription = "Bookmark article"
    )
}
</code></pre>
<p><code>Modifier.minimumInteractiveComponentSize()</code> allows your visual design to remain compact (for instance, a 24dp icon) while ensuring that the invisible, clickable hit box expands to 48dp × 48dp. This prevents touch misses for users with motor tremors or limited fine motor control.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Bad: Tightly constrained 20dp clickable area
Icon(
    imageVector = Icons.Default.Close,
    contentDescription = "Close dialog",
    modifier = Modifier
        .size(20.dp)
        .clickable { dismissDialog() } // Touch target is strictly 20dp x 20dp!
)
</code></pre>
<p>A 20dp touch target is nearly impossible to tap reliably, especially on high-density displays or while walking. Google's Accessibility Scanner will flag it as a touch target issue.</p>
<h3 id="heading-how-to-maintain-accessible-color-contrast-ratios">How to Maintain Accessible Color Contrast Ratios</h3>
<p>Color contrast measures the difference in luminance between foreground text and its background. If the contrast ratio is too low, people with low vision, color blindness, or older eyes will likely not be able to read your text.</p>
<p>WCAG 2.1 defines the following minimum contrast ratios (Android's accessibility documentation maps WCAG's point sizes to <code>sp</code>):</p>
<ul>
<li><p><strong>Normal text (smaller than 18sp, or smaller than 14sp bold):</strong> Minimum <strong>4.5:1</strong></p>
</li>
<li><p><strong>Large text (18sp or larger, or 14sp bold or larger):</strong> Minimum <strong>3.0:1</strong></p>
</li>
<li><p><strong>UI components and graphical objects:</strong> Minimum <strong>3.0:1</strong></p>
</li>
</ul>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">// Using Material 3 color tokens (paired roles maintain usable contrast)
Text(
    text = "Account Overview",
    color = MaterialTheme.colorScheme.onPrimaryContainer,
    modifier = Modifier.background(MaterialTheme.colorScheme.primaryContainer)
)

// Explicit high-contrast colors (for example, Black on White = 21:1 ratio)
Text(
    text = "Order Confirmed",
    color = Color(0xFF1B5E20), // Dark green
    modifier = Modifier.background(Color(0xFFE8F5E9)) // Light green tint
)
</code></pre>
<p>Material 3 color tokens (such as <code>onPrimaryContainer</code> paired with <code>primaryContainer</code>) are generated by the Material color system so that "on" colors maintain usable contrast against their paired container colors across both light and dark themes. You should still verify contrast for any custom brand colors you override.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Bad: Light gray on pure white (Contrast ratio ~ 1.6:1 - Fails WCAG)
Text(
    text = "Terms and Conditions apply",
    color = Color(0xFFB0B0B0),
    modifier = Modifier.background(Color.White)
)
</code></pre>
<p>Light gray text on a white background is one of the most common accessibility violations on the mobile web and in native apps. Sighted users in bright ambient light and users with low vision can't read this text.</p>
<h3 id="heading-how-to-provide-custom-clickable-labels">How to Provide Custom Clickable Labels</h3>
<p>When a user navigates to a clickable element using TalkBack, the screen reader appends default instructions such as <em>"Double-tap to activate."</em></p>
<p>You can customize this instruction using the <code>onClickLabel</code> parameter in <code>Modifier.clickable</code> to describe the precise outcome of the interaction.</p>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">ListItem(
    headlineContent = { Text("Wi-Fi Networks") },
    supportingContent = { Text("Connected to Office_5G") },
    modifier = Modifier.clickable(
        onClickLabel = "Open Wi-Fi network settings"
    ) {
        navigateToWifiSettings()
    }
)
</code></pre>
<p>TalkBack will announce: <em>"Wi-Fi Networks, Connected to Office_5G, double-tap to open Wi-Fi network settings."</em> The user knows exactly what will happen before committing to the action.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Bad: Generic clickable element without context
Card(
    modifier = Modifier.clickable { openInvoiceDetails() }
) {
    Text("Invoice #4092")
}
</code></pre>
<p>TalkBack announces: <em>"Invoice #4092, double-tap to activate."</em> The user is left uncertain whether tapping will pay the invoice, download a PDF, or open an edit screen.</p>
<h3 id="heading-how-to-establish-heading-hierarchies">How to Establish Heading Hierarchies</h3>
<p>Visual readers scan large, bold text headings to understand a screen's layout and hierarchy. Screen reader users need the exact same structural overview.</p>
<p>By applying the <code>heading()</code> semantic modifier, you designate a text node as an accessibility heading. TalkBack users can change their navigation mode to "Headings" and quickly swipe up or down to jump between sections.</p>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">Column(modifier = Modifier.padding(16.dp)) {
    // Screen title heading
    Text(
        text = "Security Settings",
        style = MaterialTheme.typography.headlineMedium,
        modifier = Modifier.semantics { heading() }
    )

    Spacer(modifier = Modifier.height(16.dp))

    // Section 1 heading
    Text(
        text = "Two-Factor Authentication",
        style = MaterialTheme.typography.titleMedium,
        modifier = Modifier.semantics { heading() }
    )
    
    // Section 1 content...

    Spacer(modifier = Modifier.height(16.dp))

    // Section 2 heading
    Text(
        text = "Connected Devices",
        style = MaterialTheme.typography.titleMedium,
        modifier = Modifier.semantics { heading() }
    )
    
    // Section 2 content...
}
</code></pre>
<p>TalkBack users can bypass dozens of individual switches and descriptions to jump directly to "Connected Devices" in seconds.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Bad: Visual heading without semantic markup
Text(
    text = "Two-Factor Authentication",
    style = MaterialTheme.typography.titleLarge // Visually large, but invisible as a heading to TalkBack
)
</code></pre>
<p>Without <code>semantics { heading() }</code>, TalkBack treats the text as regular body copy, preventing users from navigating by headings.</p>
<h3 id="heading-how-to-announce-dynamic-updates-with-live-regions">How to Announce Dynamic Updates with Live Regions</h3>
<p>When content on the screen updates asynchronously (such as a timer countdown, a file upload completion message, or a real-time validation banner), sighted users see the change immediately.</p>
<p>But screen reader users won't know that anything changed unless you mark the changing container as a <strong>live region</strong>.</p>
<p>Compose provides <code>liveRegion = LiveRegionMode.Polite</code> and <code>liveRegion = LiveRegionMode.Assertive</code>:</p>
<ul>
<li><p><code>LiveRegionMode.Polite</code><strong>:</strong> TalkBack waits until the current audio announcement is finished before reading the update. Use this for almost all status updates.</p>
</li>
<li><p><code>LiveRegionMode.Assertive</code><strong>:</strong> TalkBack announces the change immediately, ahead of other feedback. Reserve this strictly for time-sensitive, high-urgency alerts (such as emergency warnings).</p>
</li>
</ul>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">var uploadStatus by remember { mutableStateOf("Ready to upload") }

Text(
    text = uploadStatus,
    modifier = Modifier.semantics {
        liveRegion = LiveRegionMode.Polite
    }
)

// Later, when upload finishes:
LaunchedEffect(Unit) {
    performUpload()
    uploadStatus = "Upload complete! 12 files saved."
}
</code></pre>
<p>As soon as <code>uploadStatus</code> changes, TalkBack automatically speaks: <em>"Upload complete! 12 files saved,"</em> keeping non-sighted users fully informed without requiring them to search the screen.</p>
<h3 id="heading-how-to-support-dynamic-text-scaling">How to Support Dynamic Text Scaling</h3>
<p>Users with low vision often increase their system font size in Android Settings (under <strong>Display</strong> or the accessibility settings, depending on the device). Android 14 and newer support <strong>non-linear font scaling up to 200%</strong>.</p>
<p>To respect this user preference, you must define all text sizes in <code>sp</code> <strong>(scale-independent pixels)</strong>, never in <code>dp</code> or raw pixels.</p>
<h4 id="heading-what-to-do-recommended-practice">What to Do (Recommended Practice)</h4>
<pre><code class="language-kotlin">// Good: Using Material Typography (uses sp automatically)
Text(
    text = "Dashboard Summary",
    style = MaterialTheme.typography.titleMedium
)

// Good: Explicit sp sizing
Text(
    text = "Custom Label",
    fontSize = 18.sp
)
</code></pre>
<p>When a user sets their font scale to 1.5×, an 18sp font cleanly renders at 27sp, ensuring readable text.</p>
<h4 id="heading-what-not-to-do-antipattern">What Not to Do (Antipattern)</h4>
<pre><code class="language-kotlin">// Bad: Fixed dp size converted to sp (does not scale with system settings)
Text(
    text = "Fixed Size Warning",
    fontSize = with(LocalDensity.current) { 16.dp.toSp() } // Will not scale!
)
</code></pre>
<p>Sizing text with fixed <code>dp</code> measurements prevents the text from enlarging when users increase their system font size, directly violating accessibility standards.</p>
<h2 id="heading-advanced-accessibility-techniques">Advanced Accessibility Techniques</h2>
<p>For complex, production-grade applications, you can apply advanced accessibility techniques to handle non-trivial user interactions.</p>
<h3 id="heading-how-to-control-traversal-and-focus-order">How to Control Traversal and Focus Order</h3>
<p>By default, accessibility services traverse screen elements based on their visual and structural coordinates (top-to-bottom, start-to-end). In multi-column layouts, financial ledgers, or custom grids, this default order can create confusing announcements.</p>
<p>You can customize the navigation sequence using <code>traversalIndex</code> and <code>isTraversalGroup</code>:</p>
<pre><code class="language-kotlin">Column(
    modifier = Modifier.semantics { isTraversalGroup = true }
) {
    Text(
        text = "Step 1: Account Info",
        modifier = Modifier.semantics { traversalIndex = 1f }
    )
    
    Text(
        text = "Step 3: Confirmation",
        modifier = Modifier.semantics { traversalIndex = 3f }
    )
    
    Text(
        text = "Step 2: Payment Details",
        modifier = Modifier.semantics { traversalIndex = 2f }
    )
}
</code></pre>
<p>How the code works under the hood:</p>
<ol>
<li><p>Setting <code>isTraversalGroup = true</code> creates a self-contained accessibility boundary, ensuring TalkBack reads all elements inside this container before moving to other screen elements.</p>
</li>
<li><p>The <code>traversalIndex</code> floating-point value establishes the exact relative order (lowest index first). TalkBack will read Step 1, then Step 2, and finally Step 3, regardless of their visual placement in the layout.</p>
</li>
</ol>
<h3 id="heading-how-to-create-custom-accessibility-actions">How to Create Custom Accessibility Actions</h3>
<p>Consider an e-commerce product card that contains "Quick View," "Add to Wishlist," and "Add to Cart" buttons. For a screen reader user, tabbing through three separate buttons on twenty consecutive cards is tedious.</p>
<p>With <code>customActions</code>, you can attach secondary actions directly to the parent card node. When the card gains focus, TalkBack tells the user that actions are available, and the user opens the TalkBack menu to pick one.</p>
<pre><code class="language-kotlin">var isBookmarked by remember { mutableStateOf(false) }

Card(
    modifier = Modifier
        .fillMaxWidth()
        .semantics {
            customActions = listOf(
                CustomAccessibilityAction(
                    label = if (isBookmarked) "Remove from bookmarks" else "Add to bookmarks",
                    action = {
                        isBookmarked = !isBookmarked
                        true // Return true to indicate the action was handled
                    }
                ),
                CustomAccessibilityAction(
                    label = "Share article link",
                    action = {
                        shareArticle()
                        true
                    }
                )
            )
        }
) {
    // Visual card content...
}
</code></pre>
<p>When a TalkBack user focuses on the card, TalkBack informs them that custom actions are available. The user opens the TalkBack menu (or uses accessibility gestures) to see a clean list containing "Add to bookmarks" and "Share article link." This keeps your visual design streamlined while providing direct, high-efficiency navigation for power users.</p>
<h3 id="heading-how-to-design-accessible-form-inputs-and-text-fields">How to Design Accessible Form Inputs and Text Fields</h3>
<p>Accessible form inputs require more than just a visual placeholder. They need explicit labels, clear input type hints, and logical keyboard navigation actions:</p>
<pre><code class="language-kotlin">var emailValue by remember { mutableStateOf("") }

OutlinedTextField(
    value = emailValue,
    onValueChange = { emailValue = it },
    label = { Text("Work Email") },
    placeholder = { Text("alex@example.com") },
    singleLine = true,
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email,
        imeAction = ImeAction.Next
    ),
    keyboardActions = KeyboardActions(
        onNext = { /* Move focus to password field */ }
    ),
    modifier = Modifier
        .fillMaxWidth()
        .semantics {
            contentDescription = "Work email address input field"
        }
)
</code></pre>
<p>How it works under the hood:</p>
<ul>
<li><p>The <code>label</code> composable provides persistent context that remains visible even after the user types.</p>
</li>
<li><p><code>keyboardType = KeyboardType.Email</code> instructs Android to display an email-optimized keyboard (including <code>@</code> and <code>.com</code> shortcuts) and hints to accessibility services that standard email syntax is expected.</p>
</li>
<li><p><code>imeAction = ImeAction.Next</code> ensures hardware keyboard users and switch device users can smoothly advance through form fields using the keyboard Enter key.</p>
</li>
</ul>
<h3 id="heading-how-to-communicate-dynamic-error-states">How to Communicate Dynamic Error States</h3>
<p>When client-side validation fails, setting the visual border to red isn't enough. You must attach semantic error metadata so screen readers announce the validation failure immediately.</p>
<pre><code class="language-kotlin">var password by remember { mutableStateOf("") }
val isPasswordInvalid = password.isNotEmpty() &amp;&amp; password.length &lt; 8

OutlinedTextField(
    value = password,
    onValueChange = { password = it },
    label = { Text("Password") },
    isError = isPasswordInvalid,
    supportingText = {
        if (isPasswordInvalid) {
            Text(
                text = "Password must be at least 8 characters long",
                color = MaterialTheme.colorScheme.error
            )
        }
    },
    modifier = Modifier
        .fillMaxWidth()
        .semantics {
            if (isPasswordInvalid) {
                error("Password must be at least 8 characters long")
            }
        }
)
</code></pre>
<p>How it works under the hood:</p>
<p>The <code>isError = isPasswordInvalid</code> parameter handles the visual styling (red outline and error icons).</p>
<ul>
<li>The <code>error("...")</code> semantic property tells TalkBack to treat this element as invalid and announce the specific validation error message as soon as the user focuses the text field.</li>
</ul>
<h3 id="heading-how-to-manage-progress-indicators-and-asynchronous-loading">How to Manage Progress Indicators and Asynchronous Loading</h3>
<p>Loading states must clearly convey whether a task is indeterminate (in progress with unknown duration) or determinate (progressing toward 100%).</p>
<pre><code class="language-kotlin">// Indeterminate Progress (such as initial network fetch)
CircularProgressIndicator(
    modifier = Modifier.semantics {
        contentDescription = "Syncing messages, please wait"
    }
)

// Determinate Progress (such as file download)
val downloadProgress = 0.65f // 65%

LinearProgressIndicator(
    progress = { downloadProgress },
    modifier = Modifier.semantics {
        progressBarRangeInfo = ProgressBarRangeInfo(
            current = downloadProgress,
            range = 0f..1f
        )
        contentDescription = "Downloading update: ${(downloadProgress * 100).toInt()}% completed"
    }
)
</code></pre>
<p>For determinate progress indicators, <code>ProgressBarRangeInfo</code> tells assistive technologies the minimum, maximum, and current values. TalkBack interprets this information and provides periodic spoken and haptic updates as progress increases.</p>
<h3 id="heading-how-to-handle-expandable-and-collapsible-content">How to Handle Expandable and Collapsible Content</h3>
<p>Accordion menus and expandable FAQ cards must clearly indicate whether they're open or closed, and what action tapping them will trigger.</p>
<pre><code class="language-kotlin">var isExpanded by remember { mutableStateOf(false) }

Column(modifier = Modifier.fillMaxWidth()) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .clickable(
                onClickLabel = if (isExpanded) "Collapse section" else "Expand section"
            ) {
                isExpanded = !isExpanded
            }
            .semantics {
                stateDescription = if (isExpanded) "Expanded" else "Collapsed"
            }
            .padding(16.dp)
    ) {
        Text(
            text = "Frequently Asked Questions",
            style = MaterialTheme.typography.titleMedium,
            modifier = Modifier.weight(1f)
        )
        Icon(
            imageVector = if (isExpanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
            contentDescription = null // Decorative: parent Row communicates full state
        )
    }

    AnimatedVisibility(visible = isExpanded) {
        Text(
            text = "Our refund policy allows returns within 30 days of purchase...",
            modifier = Modifier.padding(16.dp)
        )
    }
}
</code></pre>
<p>The <code>stateDescription</code> announces whether the section is currently open or closed ("Expanded" or "Collapsed"). Simultaneously, <code>onClickLabel</code> clarifies the upcoming action ("Collapse section" or "Expand section"). The icon has <code>contentDescription = null</code> to avoid redundant announcements.</p>
<h3 id="heading-how-to-enhance-lazy-lists-and-large-collections">How to Enhance Lazy Lists and Large Collections</h3>
<p>When users navigate a long feed or list, they need context regarding where they are and how many items exist.</p>
<pre><code class="language-kotlin">val messages = remember { listOf("Order Shipped", "Delivery Delayed", "Payment Received") }

LazyColumn(
    modifier = Modifier.semantics {
        contentDescription = "Notifications list, ${messages.size} total alerts"
    }
) {
    itemsIndexed(messages) { index, messageText -&gt;
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 4.dp)
                .semantics {
                    contentDescription = "Notification ${index + 1} of ${messages.size}: $messageText"
                }
        ) {
            Text(
                text = messageText,
                modifier = Modifier.padding(16.dp)
            )
        }
    }
}
</code></pre>
<p>TalkBack announces positional indexes ("Notification 1 of 3: Order Shipped"), allowing screen reader users to track their progress through lists without losing their place.</p>
<h2 id="heading-how-to-test-and-debug-accessibility">How to Test and Debug Accessibility</h2>
<p>Building accessible software requires a multi-layered testing strategy: automated regression checks, on-device diagnostic tools, semantics tree inspection, and manual verification with TalkBack.</p>
<table>
<thead>
<tr>
<th>Testing Level</th>
<th>Primary Tool</th>
<th>What It Validates</th>
<th>When to Run</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Manual Verification</strong></td>
<td>TalkBack Screen Reader</td>
<td>Real non-visual user experience and gesture navigation</td>
<td>Before major feature releases</td>
</tr>
<tr>
<td><strong>Visual Auditing</strong></td>
<td>Google Accessibility Scanner</td>
<td>Automated on-screen contrast and touch target violations</td>
<td>During feature QA testing</td>
</tr>
<tr>
<td><strong>Tree Inspection</strong></td>
<td>Android Studio Layout Inspector</td>
<td>Real-time semantics tree merging and node properties</td>
<td>During active development</td>
</tr>
<tr>
<td><strong>Automated Checks</strong></td>
<td>Compose UI Test (<code>ui-test-junit4</code>)</td>
<td>Regressions on touch targets and content descriptions</td>
<td>In continuous integration (CI)</td>
</tr>
</tbody></table>
<h3 id="heading-how-to-test-manually-with-talkback">How to Test Manually with TalkBack</h3>
<p>Nothing replaces manually navigating your application using TalkBack.</p>
<h4 id="heading-how-to-enable-and-use-talkback">How to Enable and Use TalkBack</h4>
<ol>
<li><p>Open your device's <strong>Settings</strong> app and navigate to <strong>Accessibility</strong> and then <strong>TalkBack</strong>.</p>
</li>
<li><p>Toggle the switch to <strong>On</strong> and accept the system permissions. (You can also use the volume key shortcut, if enabled: hold both volume keys for a few seconds to toggle TalkBack).</p>
</li>
<li><p>Core TalkBack gestures:</p>
<ul>
<li><p><strong>Swipe Right:</strong> Move accessibility focus to the next element.</p>
</li>
<li><p><strong>Swipe Left:</strong> Move accessibility focus to the previous element.</p>
</li>
<li><p><strong>Double Tap:</strong> Activate the currently focused element.</p>
</li>
<li><p><strong>Two-Finger Swipe:</strong> Scroll lists or pages.</p>
</li>
<li><p><strong>Three-Finger Tap (or swipe down then right in one motion):</strong> Open the TalkBack menu.</p>
</li>
</ul>
</li>
</ol>
<p>What to check during your TalkBack walkthrough:</p>
<ul>
<li><p>Can you complete critical user journeys (such as registration, login, searching, and checkout) with your eyes closed?</p>
</li>
<li><p>Are all buttons and interactive controls clearly announced with meaningful names?</p>
</li>
<li><p>Does focus move in a logical, expected reading order?</p>
</li>
<li><p>Are error messages and dynamic state changes announced automatically?</p>
</li>
</ul>
<h3 id="heading-how-to-write-automated-compose-accessibility-tests">How to Write Automated Compose Accessibility Tests</h3>
<p>You can integrate automated accessibility assertions into your JUnit instrumented tests to catch missing descriptions and undersized touch targets on continuous integration (CI) servers.</p>
<h4 id="heading-add-dependencies-to-buildgradlekts">Add Dependencies to <code>build.gradle.kts</code>:</h4>
<pre><code class="language-kotlin">androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.compose.ui:ui-test-manifest")
</code></pre>
<h4 id="heading-writing-compose-accessibility-tests">Writing Compose Accessibility Tests:</h4>
<pre><code class="language-kotlin">@RunWith(AndroidJUnit4::class)
class AccessibilityTest {

    @get:Rule
    val composeTestRule = createAndroidComposeRule&lt;ComponentActivity&gt;()

    @Test
    fun testLoginButton_hasProperTouchTargetAndLabel() {
        composeTestRule.setContent {
            MaterialTheme {
                Button(
                    onClick = { /* Submit login */ },
                    modifier = Modifier.minimumInteractiveComponentSize()
                ) {
                    Text("Sign In")
                }
            }
        }

        // Verify the node exists with correct text and semantics
        composeTestRule
            .onNodeWithText("Sign In")
            .assertExists()
            .assertHasClickAction()
            .assertHeightIsAtLeast(48.dp)
            .assertWidthIsAtLeast(48.dp)
    }

    @Test
    fun testIconButton_containsContentDescription() {
        composeTestRule.setContent {
            MaterialTheme {
                IconButton(onClick = {}) {
                    Icon(
                        imageVector = Icons.Default.Favorite,
                        contentDescription = "Add to favorites"
                    )
                }
            }
        }

        // Verify content description is accurately exposed in semantics tree
        composeTestRule
            .onNode(hasContentDescription("Add to favorites"))
            .assertExists()
            .assertHasClickAction()
    }
}
</code></pre>
<h3 id="heading-step-by-step-guide-to-google-accessibility-scanner">Step-by-Step Guide to Google Accessibility Scanner</h3>
<p><strong>Google Accessibility Scanner</strong> is an Android diagnostic tool that inspects your app's rendered UI and flags accessibility violations.</p>
<h4 id="heading-how-to-install-and-set-up-accessibility-scanner">How to Install and Set Up Accessibility Scanner</h4>
<ol>
<li><p><strong>Install from Google Play:</strong> Open the Google Play Store on your test device and install <strong>Accessibility Scanner</strong> (published by Google LLC).</p>
</li>
<li><p>Enable in Accessibility Settings:</p>
<ul>
<li><p>Go to Settings then Accessibility and then Accessibility Scanner.</p>
</li>
<li><p>Toggle the switch to <strong>On</strong> and grant the required screen-reading permissions.</p>
</li>
</ul>
</li>
<li><p><strong>Locate the Floating Button:</strong> A blue floating action button with a checkmark icon <code>(✓)</code> will appear overlaid on your screen.</p>
</li>
</ol>
<h4 id="heading-running-a-scan-and-interpreting-results">Running a Scan and Interpreting Results</h4>
<p>Open your Android application and navigate to the screen you want to audit. Tap the floating blue <strong>Scanner button</strong>.</p>
<p>Then tap the <strong>Snapshot</strong> (camera) icon to analyze the static screen, or tap <strong>Record</strong> to audit a multi-step user flow.</p>
<p>The Scanner outlines each flagged UI component with an <strong>orange rectangle</strong>. Typical findings include interactive touch targets smaller than 48dp, missing labels on buttons and images, insufficient text or image contrast, and duplicate or redundant descriptions.</p>
<p>Tap any highlighted result to view a detailed breakdown explaining the problem, a link to the relevant accessibility guidance, and suggested remediation steps. Keep in mind that Scanner is a diagnostic aid. A clean scan doesn't guarantee that your app is fully accessible.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68ad0d824bbb144f1edc8183/7b7f782d-25f4-4b7a-bfc5-177648b34007.gif" alt="7b7f782d-25f4-4b7a-bfc5-177648b34007" style="display: block;" width="480" height="1040" loading="lazy">

<p><em>Figure: Google Accessibility Scanner auditing the AccessibilityDemo app, flagging an undersized 24dp touch target and displaying remediation guidance.</em></p>
<h3 id="heading-how-to-inspect-semantics-with-android-studio-layout-inspector">How to Inspect Semantics with Android Studio Layout Inspector</h3>
<p>Android Studio's <strong>Layout Inspector</strong> allows you to inspect your running Compose hierarchy in real time and view the exact Semantics Tree exposed to the operating system.</p>
<h4 id="heading-how-to-inspect-semantics-step-by-step">How to Inspect Semantics Step-by-Step</h4>
<ol>
<li><p>Run your Compose application on an emulator or physical device connected via USB debugging.</p>
</li>
<li><p>In Android Studio, open <strong>View</strong> then <strong>Tool Windows</strong> and then <strong>Layout Inspector</strong>.</p>
</li>
<li><p>In the process selector dropdown, select your application's process (such as <code>com.example.accessibilitydemo</code>).</p>
</li>
<li><p>In the Layout Inspector component tree panel on the left, navigate to the composable you want to inspect (such as the <code>Card</code> under Semantic Merging).</p>
</li>
<li><p>Look at the <strong>Attributes</strong> panel on the right. You'll see dedicated sections for:</p>
<ul>
<li><p><strong>Merged Semantics:</strong> Displays the collapsed semantic metadata exposed to accessibility services when <code>mergeDescendants = true</code> is used (including merged <code>ContentDescription</code>, <code>Text</code> lists, <code>OnClick</code> actions, and container flags).</p>
</li>
<li><p><strong>Declared Semantics:</strong> Shows the explicit semantic properties directly attached to that specific composable node.</p>
</li>
</ul>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/68ad0d824bbb144f1edc8183/c9d918df-794b-41ff-9771-3ec4b772a5f8.png" alt="c9d918df-794b-41ff-9771-3ec4b772a5f8" style="display: block;" width="1024" height="534" loading="lazy">

<p><em>Figure: Android Studio Layout Inspector inspecting the AccessibilityDemo app, displaying the Component Tree on the left, visual wireframes in the center, and the Merged Semantics attributes panel on the right.</em></p>
<p>Using Layout Inspector provides visual confirmation that:</p>
<ul>
<li><p><code>semantics(mergeDescendants = true)</code> is properly grouping disparate children into a single node.</p>
</li>
<li><p>Decorative icons are successfully excluded from the accessibility tree.</p>
</li>
<li><p>Click actions (<code>OnClick: AccessibilityAction</code>) and custom actions are correctly wired to the composable.</p>
</li>
</ul>
<h2 id="heading-real-world-accessible-ui-patterns">Real-World Accessible UI Patterns</h2>
<p>Here are complete, production-ready implementations of common UI patterns:</p>
<h3 id="heading-fully-accessible-login-form">Fully Accessible Login Form</h3>
<p>Forms are critical entry points. This implementation combines heading semantics, email input validation, dynamic error announcements, and proper touch target sizing:</p>
<pre><code class="language-kotlin">@Composable
fun AccessibleLoginForm(
    onLoginSubmitted: (String, String) -&gt; Unit
) {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    var isSubmitted by remember { mutableStateOf(false) }

    val isEmailInvalid = isSubmitted &amp;&amp; !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()
    val isPasswordInvalid = isSubmitted &amp;&amp; password.length &lt; 8

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp)
    ) {
        // 1. Designated Screen Title Heading
        Text(
            text = "Welcome Back",
            style = MaterialTheme.typography.headlineLarge,
            modifier = Modifier.semantics { heading() }
        )

        Text(
            text = "Sign in to access your account",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )

        Spacer(modifier = Modifier.height(24.dp))

        // 2. Accessible Email Input
        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email Address") },
            isError = isEmailInvalid,
            singleLine = true,
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Email,
                imeAction = ImeAction.Next
            ),
            supportingText = {
                if (isEmailInvalid) {
                    Text(
                        text = "Please enter a valid email address",
                        color = MaterialTheme.colorScheme.error
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .semantics {
                    if (isEmailInvalid) {
                        error("Please enter a valid email address")
                    }
                }
        )

        Spacer(modifier = Modifier.height(16.dp))

        // 3. Accessible Password Input
        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            isError = isPasswordInvalid,
            singleLine = true,
            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Password,
                imeAction = ImeAction.Done
            ),
            supportingText = {
                if (isPasswordInvalid) {
                    Text(
                        text = "Password must be at least 8 characters long",
                        color = MaterialTheme.colorScheme.error
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .semantics {
                    if (isPasswordInvalid) {
                        error("Password must be at least 8 characters long")
                    }
                }
        )

        Spacer(modifier = Modifier.height(24.dp))

        // 4. Accessible Submit Button
        Button(
            onClick = {
                isSubmitted = true
                if (!isEmailInvalid &amp;&amp; !isPasswordInvalid) {
                    onLoginSubmitted(email, password)
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .minimumInteractiveComponentSize()
                .semantics {
                    contentDescription = "Sign in to your account"
                }
        ) {
            Text("Sign In")
        }
    }
}
</code></pre>
<p>Why this pattern works:</p>
<ol>
<li><p><strong>Screen Heading:</strong> TalkBack users can instantly jump to "Welcome Back" when entering the screen.</p>
</li>
<li><p><strong>Error Semantics:</strong> If validation fails, <code>error("...")</code> ensures TalkBack immediately speaks the validation requirement when the text field receives focus.</p>
</li>
<li><p><strong>Keyboard Routing:</strong> <code>ImeAction.Next</code> and <code>ImeAction.Done</code> guide keyboard and switch users smoothly between input fields.</p>
</li>
</ol>
<h3 id="heading-e-commerce-product-card-with-custom-actions">E-Commerce Product Card with Custom Actions</h3>
<p>This pattern demonstrates how to combine <code>mergeDescendants = true</code> with <code>customActions</code> to create a concise, power-user-friendly card:</p>
<pre><code class="language-kotlin">data class Product(
    val id: String,
    val title: String,
    val priceFormatted: String,
    val rating: Float,
    val imageRes: Int
)

@Composable
fun AccessibleProductCard(
    product: Product,
    onCardClick: () -&gt; Unit,
    onToggleFavorite: () -&gt; Unit,
    onAddToCart: () -&gt; Unit
) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClickLabel = "View product details") { onCardClick() }
            .semantics(mergeDescendants = true) {
                // Group all descriptive properties into one coherent announcement
                contentDescription = "${product.title}, Price: ${product.priceFormatted}, Rated ${product.rating} out of 5 stars"
                
                // Expose secondary operations as custom accessibility actions
                customActions = listOf(
                    CustomAccessibilityAction("Add to shopping cart") {
                        onAddToCart()
                        true
                    },
                    CustomAccessibilityAction("Save to favorites") {
                        onToggleFavorite()
                        true
                    }
                )
            }
    ) {
        Row(
            modifier = Modifier.padding(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Image(
                painter = painterResource(product.imageRes),
                contentDescription = null, // Decorative: covered by merged description
                modifier = Modifier
                    .size(80.dp)
                    .clip(RoundedCornerShape(8.dp))
            )

            Spacer(modifier = Modifier.width(16.dp))

            Column(modifier = Modifier.weight(1f)) {
                Text(
                    text = product.title,
                    style = MaterialTheme.typography.titleMedium
                )
                Text(
                    text = product.priceFormatted,
                    style = MaterialTheme.typography.bodyLarge,
                    fontWeight = FontWeight.Bold
                )
                Text(
                    text = "★ ${product.rating}",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
        }
    }
}
</code></pre>
<p>Why this pattern works:</p>
<ol>
<li><p><strong>Single Semantic Stop:</strong> Instead of swiping four times through separate image and text views, TalkBack reads the entire card in one unified statement.</p>
</li>
<li><p><strong>Action Shortcuts:</strong> Users can add items to their cart or favorites directly from the TalkBack actions menu without navigating into the details page.</p>
</li>
</ol>
<h3 id="heading-tab-navigation-with-selection-state">Tab Navigation with Selection State</h3>
<p>This pattern demonstrates accessible tab bar navigation using <code>stateDescription</code> and custom tab announcements:</p>
<pre><code class="language-kotlin">@Composable
fun AccessibleTabNavigation(
    tabs: List&lt;String&gt;,
    selectedTabIndex: Int,
    onTabSelected: (Int) -&gt; Unit
) {
    TabRow(
        selectedTabIndex = selectedTabIndex,
        modifier = Modifier.semantics {
            contentDescription = "Navigation tabs, ${tabs[selectedTabIndex]} selected"
        }
    ) {
        tabs.forEachIndexed { index, title -&gt;
            val isSelected = selectedTabIndex == index
            Tab(
                selected = isSelected,
                onClick = { onTabSelected(index) },
                modifier = Modifier.semantics {
                    role = Role.Tab
                    stateDescription = if (isSelected) "Selected" else "Not selected"
                    contentDescription = "$title tab"
                }
            ) {
                Text(
                    text = title,
                    modifier = Modifier.padding(vertical = 16.dp)
                )
            }
        }
    }
}
</code></pre>
<p>Why this pattern works:</p>
<ol>
<li><p><strong>Explicit Role:</strong> Marking each item with <code>Role.Tab</code> informs accessibility services that this is a selectable tab container.</p>
</li>
<li><p><strong>Selection Feedback:</strong> The <code>stateDescription</code> tells the user whether a tab is currently active before they tap it.</p>
</li>
</ol>
<h3 id="heading-confirmation-dialog-with-action-descriptions">Confirmation Dialog with Action Descriptions</h3>
<p>This pattern shows how to structure an accessible confirmation dialog:</p>
<pre><code class="language-kotlin">@Composable
fun AccessibleDeleteConfirmationDialog(
    itemName: String,
    onDismissRequest: () -&gt; Unit,
    onConfirmDelete: () -&gt; Unit
) {
    AlertDialog(
        onDismissRequest = onDismissRequest,
        title = {
            Text(
                text = "Delete Item?",
                style = MaterialTheme.typography.headlineSmall,
                modifier = Modifier.semantics { heading() }
            )
        },
        text = {
            Text("Are you sure you want to permanently delete \"$itemName\"? This action cannot be undone.")
        },
        confirmButton = {
            TextButton(
                onClick = onConfirmDelete,
                modifier = Modifier.semantics {
                    contentDescription = "Confirm deletion of $itemName"
                }
            ) {
                Text("Delete", color = MaterialTheme.colorScheme.error)
            }
        },
        dismissButton = {
            TextButton(
                onClick = onDismissRequest,
                modifier = Modifier.semantics {
                    contentDescription = "Cancel deletion and close dialog"
                }
            ) {
                Text("Cancel")
            }
        },
        modifier = Modifier.semantics {
            contentDescription = "Delete item confirmation dialog"
        }
    )
}
</code></pre>
<p>Why this pattern works:</p>
<ol>
<li><p><strong>Clear Focus:</strong> When the dialog appears, TalkBack automatically traps focus within the dialog bounds so users can't accidentally click background elements.</p>
</li>
<li><p><strong>Context-Rich Buttons:</strong> Button descriptions explain the exact consequence of clicking ("Confirm deletion of Shopping List" rather than just "Delete").</p>
</li>
</ol>
<h2 id="heading-accessibility-audit-checklist">Accessibility Audit Checklist</h2>
<p>Before releasing your app to production or submitting it to app stores, run through this accessibility audit checklist:</p>
<h3 id="heading-visual-and-typography">Visual and Typography</h3>
<ul>
<li><p><strong>Scalable Text:</strong> Define all font sizes in <code>sp</code> (never fixed <code>dp</code>) so text scales cleanly up to 200%.</p>
</li>
<li><p><strong>Color Contrast:</strong> Maintain at least a <strong>4.5:1</strong> contrast ratio for normal text and <strong>3.0:1</strong> for large text and essential UI components against their backgrounds.</p>
</li>
<li><p><strong>Color Independence:</strong> Never convey information through color alone. Always pair color cues with text labels or distinct icons.</p>
</li>
</ul>
<h3 id="heading-interactive-elements-and-touch-targets">Interactive Elements and Touch Targets</h3>
<ul>
<li><p><strong>Touch Target Sizing:</strong> Ensure every clickable or interactive component has a minimum hit target of <strong>48dp × 48dp</strong> using <code>Modifier.minimumInteractiveComponentSize()</code>.</p>
</li>
<li><p><strong>Actionable Descriptions:</strong> Provide descriptive, action-oriented <code>contentDescription</code> strings on all functional icon buttons and interactive images.</p>
</li>
<li><p><strong>Decorative Elements:</strong> Set <code>contentDescription = null</code> on purely decorative icons and illustrations to keep TalkBack feedback concise.</p>
</li>
<li><p><strong>Click Context:</strong> Provide custom <code>onClickLabel</code> parameters on cards, list items, and custom buttons to clarify the outcome before activation.</p>
</li>
</ul>
<h3 id="heading-screen-structure-and-navigation">Screen Structure and Navigation</h3>
<ul>
<li><p><strong>Accessibility Headings:</strong> Mark major section titles and screen headers with <code>Modifier.semantics { heading() }</code> for rapid heading navigation.</p>
</li>
<li><p><strong>Semantic Merging:</strong> Group related visual sub-elements (such as ratings or multi-text card headers) using <code>Modifier.semantics(mergeDescendants = true)</code>.</p>
</li>
<li><p><strong>Live Announcements:</strong> Designate asynchronous UI updates with <code>liveRegion = LiveRegionMode.Polite</code> so TalkBack announces background changes.</p>
</li>
<li><p><strong>Form Optimization:</strong> Specify appropriate <code>keyboardType</code> and <code>imeAction</code> configurations on all text inputs.</p>
</li>
<li><p><strong>Validation Feedback:</strong> Declare active input error states using <code>Modifier.semantics { error("...") }</code>.</p>
</li>
</ul>
<h3 id="heading-testing-and-verification">Testing and Verification</h3>
<ul>
<li><p><strong>Automated Unit Tests:</strong> Add Compose accessibility assertions in continuous integration to catch touch target and missing label regressions.</p>
</li>
<li><p><strong>On-Device Diagnostic Audit:</strong> Run Google Accessibility Scanner across all key app screens to catch contrast or sizing defects.</p>
</li>
<li><p><strong>Semantics Tree Inspection:</strong> Use Android Studio Layout Inspector to verify merged semantics and declared accessibility actions.</p>
</li>
<li><p><strong>Manual Screen Reader Walkthrough:</strong> Complete end-to-end user journeys (login, checkout, navigation) with TalkBack enabled.</p>
</li>
</ul>
<h2 id="heading-conclusion-and-next-steps">Conclusion and Next Steps</h2>
<p>Building accessible applications in Jetpack Compose doesn't mean just retrofitting code at the end of a project. You need to understand Compose's dual-tree architecture and design your user interface so that both visual pixels and semantic metadata accurately represent your application's intent.</p>
<p>By applying semantic properties, ensuring 48dp touch targets, maintaining WCAG contrast ratios, and verifying your work with TalkBack and Google Accessibility Scanner, you ensure that your Android applications are welcoming, compliant, and intuitive for all users worldwide.</p>
<h2 id="heading-essential-resources">Essential Resources</h2>
<p>To deepen your understanding of Android accessibility, consult these essential references:</p>
<ul>
<li><p><a href="https://developer.android.com/develop/ui/compose/accessibility">Android Developers Official Guide: Accessibility in Jetpack Compose</a></p>
</li>
<li><p><a href="https://developer.android.com/develop/ui/compose/accessibility/semantics">Android Developers Official Guide: Semantics in Compose</a></p>
</li>
<li><p><a href="https://www.w3.org/WAI/WCAG21/quickref/">W3C Web Content Accessibility Guidelines (WCAG) 2.1 Quick Reference</a></p>
</li>
<li><p><a href="https://m3.material.io/foundations/accessible-design/overview">Google Material Design 3: Accessible Design Foundations</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Master Kotlin & Android 60-Hour Course ]]>
                </title>
                <description>
                    <![CDATA[ Do you want to create the next groundbreaking mobile app? Kotlin, a modern and powerful language officially backed by Google, not only makes Android development more efficient and enjoyable but also opens doors to diverse programming opportunities be... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/master-kotlin-and-android-60-hour-course/</link>
                <guid isPermaLink="false">6824aba7be2c002301d59188</guid>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 14 May 2025 14:41:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747233684976/019ffd11-b74c-437d-815f-857ab3465317.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Do you want to create the next groundbreaking mobile app? Kotlin, a modern and powerful language officially backed by Google, not only makes Android development more efficient and enjoyable but also opens doors to diverse programming opportunities beyond mobile. Whether you're looking to build innovative applications, solve real-world problems, or join a thriving global community of developers, learning Kotlin and Android is a great investment in your future.</p>
<p>We just posted a massive 60-hour Kotlin and Android Development course on the freeCodeCamp.org YouTube channel. This course will help you master modern Android practices. Alexandru Cristian developed this course. It’s packed with hands-on practice, ensuring you not only learn the theory but also apply it by building multiple real-world applications.</p>
<p>This is a thorough exploration of the Kotlin programming language and the Android development ecosystem. Here’s a glimpse of what you’ll learn:</p>
<h3 id="heading-kotlin-from-the-ground-up"><strong>Kotlin from the ground up</strong></h3>
<ul>
<li><p>Solidify your understanding of Kotlin syntax, variables, operators, control flow (loops, conditionals), and null safety.</p>
<ul>
<li><p>Dive deep into Object-Oriented Programming (OOP) with Kotlin, covering classes, inheritance, interfaces, abstract classes, and data classes.</p>
</li>
<li><p>Master Kotlin Collections (lists, sets, maps) and powerful functions to manipulate them.</p>
</li>
<li><p>Explore advanced concepts like Generics, Lambda functions, and Kotlin Coroutines for efficient asynchronous programming.</p>
</li>
<li><p>Even touch upon SQL basics to understand data persistence.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-comprehensive-android-development"><strong>Comprehensive android development</strong></h3>
<ul>
<li><p>Get started with Android Studio and understand the Android project structure.</p>
<ul>
<li><p>Learn traditional UI development with XML, including various layouts (LinearLayout, RelativeLayout, ConstraintLayout) and UI widgets.</p>
</li>
<li><p>Master Android Activities and Fragments, their lifecycles, and how to navigate between screens using Intents and the modern Navigation Component.</p>
</li>
<li><p>Build dynamic lists with RecyclerView.</p>
</li>
<li><p>Understand and implement Material Design principles.</p>
</li>
<li><p>Work with data persistence using Room Database and connect to the cloud with Firebase Firestore.</p>
</li>
<li><p>Make network requests and handle APIs using Retrofit and parse JSON data.</p>
</li>
<li><p>Implement robust app architecture using MVVM (Model-View-ViewModel), LiveData, and potentially Dependency Injection.</p>
</li>
<li><p>Get an introduction to the future of Android UI with Jetpack Compose.</p>
</li>
</ul>
</li>
</ul>
<p>Theory is important, but practice is what makes a developer. Throughout this 60-hour course, you'll be building a portfolio of applications. The final project is an Uber clone that will have you implementing features like maps integration, user authentication, real-time location tracking, and more, demonstrating truly professional-grade development techniques.</p>
<h3 id="heading-start-learning-today">Start learning today</h3>
<p>Learning Kotlin and Android development opens doors to an exciting career in mobile technology. Android powers billions of devices worldwide, and skilled developers are in constant demand. Kotlin is a modern, concise, and powerful language officially supported by Google for Android development, making it an essential skill for today's app creators.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/blKkRoZPxLc">the freeCodeCamp.org YouTube channel</a> (60-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/blKkRoZPxLc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Concurrency in Kotlin Server-Side Development ]]>
                </title>
                <description>
                    <![CDATA[ By Faith Oyama Imagine you're running a bustling restaurant. Orders fly in, dishes need cooking, tables require clearing, and happy customers demand attention. How can you handle all this chaos without everything turning into a total disaster? This i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/concurrency-in-kotlin-server-side-development/</link>
                <guid isPermaLink="false">66d45edb230dff01669057f3</guid>
                
                    <category>
                        <![CDATA[ concurrency ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 05 Jan 2024 23:59:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/concurrency.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Faith Oyama</p>
<p>Imagine you're running a bustling restaurant. Orders fly in, dishes need cooking, tables require clearing, and happy customers demand attention. How can you handle all this chaos without everything turning into a total disaster? This is where concurrency comes in.</p>
<p>In the world of server-side development, things can get just as hectic. Users fire off requests, databases need querying, calculations demand crunching, and all this needs to happen smoothly and efficiently. Without concurrency, it's like having one overworked chef trying to do everything.</p>
<p>But with concurrency, it's like adding a whole team of skilled multitaskers to your kitchen. You have specialized "coroutines" handling different tasks – one taking orders, another cooking, one washing dishes, and so on. Each works simultaneously, but in a coordinated way, ensuring your customers get their delicious meals fast and with a smile.</p>
<h2 id="heading-examples-of-concurrency">Examples of Concurrency</h2>
<p>Here are some real-world examples of how concurrency works in server-side development:</p>
<p><strong>Serving multiple users at once:</strong> Imagine your website gets slammed by eager shoppers during a flash sale. Without concurrency, each user request would have to wait its turn, leading to frustratingly slow loading times. </p>
<p>But with coroutines, multiple requests can be processed simultaneously, keeping everyone happy and shopping with ease.</p>
<p><strong>Processing data pipelines:</strong> Do you work with really large datasets? Concurrency can break them down and analyze them bit by bit.</p>
<p><strong>Handling asynchronous requests:</strong> Think of API calls, database queries, or file uploads. These often take time to complete. With concurrency, your main program doesn't have to sit and wait. It can launch separate coroutines to handle these requests and get back to other tasks, keeping everything running smoothly.</p>
<p>Concurrency isn't just some fancy buzzword – it's a powerful tool that lets you handle the ever-growing demands of server-side development with ease and efficiency. </p>
<p>Now, we'll dive deeper into the differences between threads and coroutines, the fundamental building blocks of concurrent programming in Kotlin.</p>
<h2 id="heading-threads-vs-coroutines">Threads vs. Coroutines</h2>
<p>Now, let's talk about the two main players on this team: threads and coroutines. </p>
<h3 id="heading-what-are-threads">What are Threads?</h3>
<p>Threads are powerful, and capable of handling complex tasks – but they're also a bit resource-hungry. Each thread requires its memory space and attention from the operating system. </p>
<p>This can be great for demanding tasks like breaking down big numbers or sending critical emails, but if you have too many threads running around, your server starts getting overwhelmed, leading to slowdowns and even crashes.</p>
<h3 id="heading-what-are-coroutines">What are Coroutines?</h3>
<p>Coroutines are lightweight, flexible, and able to switch between tasks in a flash. They don't need their dedicated tables, they share resources efficiently, and they can even pause their work gracefully if something else needs immediate attention. </p>
<p>Think of them as taking orders, checking on tables, and cleaning dishes – always contributing, but in a light and adaptable way.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/kotin.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Table showing differences bewteen threads and coroutines.</em></p>
<p>So, which of them should you choose? Well, it depends! For heavy lifting, threads are strong and reliable. But for the everyday hustle and bustle, coroutines are your agile friends. </p>
<p>Kotlin favours coroutines for concurrent programming because they're more efficient and easier to manage, especially when dealing with lots of asynchronous tasks.</p>
<h2 id="heading-how-to-launch-coroutines">How to Launch Coroutines</h2>
<p>In your server-side code, there are two main ways to launch coroutines.</p>
<h3 id="heading-launch-and-forget-using-the-launch-keyword">Launch and Forget: Using the <code>launch</code> Keyword</h3>
<p>This fires up a new coroutine and sends it off to its assigned task, but doesn't wait for it to finish. </p>
<p>Here's how it looks in code:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">updateCustomerOrder</span><span class="hljs-params">(
  orderId: <span class="hljs-type">Int</span>,
  newDish: <span class="hljs-type">String</span>
)</span></span> {
  launch {
    updateOrderInDatabase(orderId, newDish)
  }
  sendConfirmationEmail(orderId)
}
</code></pre>
<p>This is ideal for tasks that don't need immediate feedback. You can launch multiple coroutines like this without overloading your server, as they work independently and share resources efficiently.</p>
<h3 id="heading-wait-and-receive-the-async-keyword">Wait and Receive: The <code>async</code> Keyword</h3>
<p>Now, let's say you need to know the total bill before you can settle up with the customer. This is where <code>async</code> comes in. It's like sending an assistant to calculate the bill and then patiently waiting for them to return with the answer.</p>
<p>Here's how it works:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">calculateBill</span><span class="hljs-params">(orderId: <span class="hljs-type">Int</span>)</span></span>: <span class="hljs-built_in">Double</span> {
  <span class="hljs-keyword">val</span> billResult = async {
    calculateBillFromDatabase(orderId)
  }
  <span class="hljs-keyword">val</span> totalBill = billResult.await()
  <span class="hljs-keyword">return</span> totalBill
}
</code></pre>
<p>This is useful for tasks where you need the result before proceeding. The <code>async</code> keyword creates a coroutine that calculates the bill in the background (performs the task), but the main program pauses and waits until the result is ready.</p>
<h2 id="heading-channels-communication-lifelines">Channels: Communication Lifelines</h2>
<p>Channels allow coroutines to send and receive messages in a safe and organized way, even when things get crazy. Here's how they work:</p>
<h3 id="heading-one-way-streets-send-channels">One-Way Streets: Send Channels</h3>
<p>A send channel allows one coroutine to send a message that another coroutine can receive on the other end. Only one direction, just like a one-way street.</p>
<h3 id="heading-bi-directional-bridges-receive-channels">Bi-Directional Bridges: Receive Channels</h3>
<p>Receive channels allow a coroutine to wait for and receive a message that was sent on the corresponding send channel. Two-way communication, like a bridge in both directions.</p>
<h3 id="heading-putting-channels-to-work">Putting Channels to Work:</h3>
<p>Here's an example of using channels to update customer orders:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> orderUpdatesChannel = Channel&lt;Pair&lt;<span class="hljs-built_in">Int</span>, String&gt;&gt;()

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">updateCustomerOrder</span><span class="hljs-params">(orderId: <span class="hljs-type">Int</span>, newDish: <span class="hljs-type">String</span>)</span></span> {
  launch {
    updateOrderInDatabase(orderId, newDish)
    orderUpdatesChannel.send(orderId to newDish)
  }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendOrderConfirmationEmails</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
    <span class="hljs-keyword">val</span> orderUpdate = orderUpdatesChannel.receive()
    <span class="hljs-keyword">val</span> (updatedOrderId, newDish) = orderUpdate
    sendConfirmationEmail(updatedOrderId)
  }
}
</code></pre>
<p>In this case, the <code>updateCustomerOrder</code> coroutine sends the updated order details through the <code>orderUpdatesChannel</code>. The <code>sendOrderConfirmationEmails</code> coroutine constantly waits on the channel, receiving updates one by one and sending out confirmation emails.</p>
<h2 id="heading-structured-concurrency">Structured Concurrency</h2>
<p>Think of structured concurrency like assigning roles and responsibilities in your kitchen. It helps you:</p>
<ol>
<li><strong>Define the scope:</strong> You can create coroutine contexts that provide specific resources and boundaries for your coroutines to work within. This keeps things organized and prevents rogue coroutines from mucking up the system.</li>
<li><strong>Cancellation:</strong> Imagine a customer changing their order halfway through cooking. Structured concurrency allows you to easily cancel the wrong dish and start preparing the new one, without everything crumbling into a greasy mess.</li>
<li><strong>Supervision:</strong> Structured concurrency lets you set up supervisors who monitor their "child" coroutines, ensuring they finish their tasks properly or handle errors gracefully.</li>
</ol>
<h3 id="heading-key-tools-for-structured-concurrency">Key tools for structured concurrency:</h3>
<p><strong>Dispatchers:</strong> They control where and how your coroutines run, like assigning them to specific threads or pools.</p>
<p><strong>Jobs:</strong> Think of them as the tasks themselves, assigned to specific coroutines within a context. You can track their progress, cancel them if needed, and keep things organized.</p>
<p><strong>Supervisor Jobs:</strong> They supervise child jobs, handling failures and propagating them properly, preventing errors from cascading and ruining the whole meal.</p>
<p>Different types of tasks in your server-side code demand different environments. This is where the various dispatcher types come in:</p>
<ol>
<li><strong>The Main Dispatcher:</strong> Think of it as the front of the house, handling UI updates and interacting directly with the customer (user). It's a single thread, ensuring smooth and responsive interactions without any chaotic multitasking.</li>
<li><strong>The Default Dispatcher:</strong> This is the workhorse for general computation tasks. It uses a thread pool, assigning coroutines to available threads. Great for CPU-intensive calculations, database processing, and other heavy lifting.</li>
<li><strong>The IO Dispatcher:</strong> This dispatcher handles blocking I/O operations like network calls, file access, or database queries. </li>
<li><strong>Custom Dispatchers:</strong> You can create custom dispatchers with specific thread pools or even single threads, tailoring them to the needs of your unique tasks.</li>
</ol>
<p>Choosing the right dispatcher is very important for optimizing performance and avoiding congestion. Here are some tips:</p>
<ul>
<li>Use the main dispatcher only for UI updates and user interaction.</li>
<li>Default dispatcher for most CPU-intensive tasks.</li>
<li>IO dispatcher for any blocking I/O operations.</li>
<li>Consider custom dispatchers for specific high-volume or sensitive tasks.</li>
</ul>
<h2 id="heading-flows">Flows</h2>
<p>Imagine your restaurant is booming, orders flying in faster than the chefs can cook. How do you handle this data deluge without everything turning into a soggy mess?</p>
<p>Think of Flows as streams of data flowing through your server-side code, like the continuous stream of orders coming from the tables. Instead of dealing with each dish individually, Flows let you handle the data continuously, adapting to the pace and transforming it on the fly.</p>
<p>Here's why Flows are a game-changer:</p>
<ul>
<li>No more waiting around for data to arrive. Flows let you launch coroutines to handle the stream asynchronously, keeping your main program free to keep taking orders and managing the overall experience.</li>
<li>Flows allow you to extract insights, generate reports, or trigger actions in real-time.</li>
<li>Flows automatically adjust their pace based on downstream processing capabilities, preventing backlogs and ensuring smooth data flow through your system.</li>
<li>Errors are handled delicately with flows, which transmit them without bringing down the entire service.</li>
</ul>
<p>Here's an example of using Flows to process a stream of sensor readings:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> sensorReadingsFlow = sensorManager.readings()
    .filter { reading -&gt; reading.temperature &gt; <span class="hljs-number">80</span> } 
    .map { reading -&gt; <span class="hljs-string">"Alert! Sensor <span class="hljs-subst">${reading.id}</span> at <span class="hljs-subst">${reading.temperature}</span> degrees!"</span> }    
    .launchIn(Dispatchers.IO) 
    .onEach { message -&gt; logger.warn(message) } 
    .collectLatest { message -&gt; sendPushNotification(message) }
</code></pre>
<p>This Flow reads sensor readings continuously, filters for high temperatures, transforms them into alert messages, and sends them to users, all in a non-blocking, resilient way.</p>
<p>Flows are a powerful tool for modern server-side development. They let you embrace the world of asynchronous data processing with grace and efficiency, keeping your code responsive, scalable, and ready to handle whatever data banquet your users throw at you.</p>
<h2 id="heading-testing-your-concurrency-setup">Testing Your Concurrency Setup</h2>
<p>So, you've built your server-side kitchen with agile coroutines, smooth communication channels, and efficient dispatchers. Your data flows like a rushing stream, and your customers (users) are singing your praises. But before you hang the "Open" sign permanently, there's one more crucial step: testing your concurrency magic.</p>
<p>Testing helps you uncover edge cases, prevent crashes, and ensure everything runs smoothly even under heavy load.</p>
<p>Here are some key points for testing concurrent code:</p>
<ul>
<li><strong>Focus on isolation:</strong> Test individual coroutines and channels in isolation to identify problems in specific components. You can use libraries like kotlinx-coroutines-test to control time and simulate asynchronous behavior.</li>
<li><strong>Mock dependencies:</strong> External dependencies like databases or APIs can add complexity. Mocking these dependencies allows you to focus on coroutine behavior without introducing real-world uncertainties.</li>
<li><strong>Verify state changes:</strong> Ensure coroutines update data structures and flags correctly as they execute. Assert expected values at different points in the execution flow.</li>
<li><strong>Stress test performance:</strong> Push your code to its limits with high volume or complex scenarios. This helps you identify bottlenecks and ensure your system scales gracefully.</li>
</ul>
<p>Remember, testing concurrent code is not always straightforward. Be patient, experiment with different methods, and don't be afraid to seek help from experienced developers and testing frameworks.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We've explored agile coroutines dancing across tasks, efficient channels keeping them in sync, and smart dispatchers directing the flow. We've seen how Flows seamlessly handle data streams, and we've learned the importance of robust testing to ensure everything runs smoothly.</p>
<p>Now, with this knowledge, you should understand the concept of concurrency in your Kotlin applications. Embrace it, use it wisely, and watch your applications soar to new heights of responsiveness, scalability, and efficiency.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Secure Kotlin Server Applications ]]>
                </title>
                <description>
                    <![CDATA[ By Faith Oyama In server-side application development using Kotlin, taking robust security measures is important. Developers encounter various threats and vulnerabilities that can compromise applications. This article delves into comprehensive securi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/securing-kotlin-server-applications/</link>
                <guid isPermaLink="false">66d45eeed1ffc3d3eb89dde3</guid>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 04 Jan 2024 22:33:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Securing-Kotlin-Server-Applications-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Faith Oyama</p>
<p>In server-side application development using Kotlin, taking robust security measures is important. Developers encounter various threats and vulnerabilities that can compromise applications. This article delves into comprehensive security strategies tailored for Kotlin server applications, aiming to equip developers with the knowledge to fortify their systems against potential risks.</p>
<p>Security in Kotlin server applications isn't just about preventing unauthorized access. It's also about safeguarding against diverse threats such as injection attacks, cross-site scripting (XSS), and data breaches. </p>
<p>In this article, we'll explore fundamental security practices, authentication methods, access control, input validation, secure communication, and much more.</p>
<h2 id="heading-authentication-mechanisms">Authentication Mechanisms</h2>
<p>In Kotlin server applications, implementing robust authentication mechanisms is important in controlling access and ensuring data security. One popular method is token-based authentication, which employs tokens (like JSON Web Tokens - JWTs) for user verification. It offers scalability and flexibility, enabling stateless authentication.</p>
<p>Let's delve into a simple implementation of JWT-based authentication using the java-jwt library:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> com.auth0.jwt.JWT
<span class="hljs-keyword">import</span> com.auth0.jwt.algorithms.Algorithm
<span class="hljs-keyword">import</span> java.util.*

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateToken</span><span class="hljs-params">(userId: <span class="hljs-type">String</span>)</span></span>: String {
    <span class="hljs-keyword">val</span> algorithm = Algorithm.HMAC256(<span class="hljs-string">"secret_key"</span>)
    <span class="hljs-keyword">return</span> JWT.create()
        .withIssuer(<span class="hljs-string">"your_issuer"</span>)
        .withSubject(userId)
        .withExpiresAt(Date(System.currentTimeMillis() + <span class="hljs-number">3600000</span>))
        .sign(algorithm)
}
</code></pre>
<p>This function generates a JWT token for a given user ID, signed using an HMAC algorithm. Ensure to securely manage the secret key.</p>
<h2 id="heading-authorization-and-access-control">Authorization and Access Control</h2>
<p>Authorization involves defining and managing user roles and permissions to regulate access to various parts of an application. In Kotlin, implementing RBAC (role-based access control) ensures proper access control within the server.</p>
<p>Let's create a simple RBAC setup using Ktor:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserRole</span> </span>{
ADMIN, USER, GUEST
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">checkPermission</span><span class="hljs-params">(userRole: <span class="hljs-type">UserRole</span>, resource: <span class="hljs-type">String</span>, action: <span class="hljs-type">String</span>)</span></span>: <span class="hljs-built_in">Boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">when</span> (userRole) {
        UserRole.ADMIN -&gt; <span class="hljs-literal">true</span>
        UserRole.USER -&gt; resource == <span class="hljs-string">"profile"</span> &amp;&amp; (action == <span class="hljs-string">"read"</span> || action == <span class="hljs-string">"write"</span>)
        UserRole.GUEST -&gt; resource == <span class="hljs-string">"public"</span> &amp;&amp; action == <span class="hljs-string">"read"</span>
    }
}
</code></pre>
<p>In this example, <code>checkPermission()</code> validates whether a user with a specific role has permission to perform a particular action on a resource.</p>
<h2 id="heading-input-validation-and-data-sanitization">Input Validation and Data Sanitization</h2>
<p>Input validation is crucial to prevent security vulnerabilities like SQL injection and XSS attacks. Kotlin, when used in server applications, should meticulously validate and sanitize user inputs before processing.</p>
<p>Let's consider an example of input validation using regular expressions in Kotlin:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">isValidEmail</span><span class="hljs-params">(email: <span class="hljs-type">String</span>)</span></span>: <span class="hljs-built_in">Boolean</span> {
    <span class="hljs-keyword">val</span> emailRegex = <span class="hljs-string">"^[A-Za-z](.*)([@]{1})(.{1,})(\\.)(.{1,})"</span>
    <span class="hljs-keyword">return</span> email.matches(emailRegex.toRegex())
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sanitizeInput</span><span class="hljs-params">(input: <span class="hljs-type">String</span>)</span></span>: String {
    <span class="hljs-keyword">return</span> input.replace(<span class="hljs-string">"&lt;"</span>, <span class="hljs-string">"&amp;lt;"</span>).replace(<span class="hljs-string">"&gt;"</span>, <span class="hljs-string">"&amp;gt;"</span>)
}
</code></pre>
<p>The <code>isValidEmail()</code> function uses a regular expression to verify if an email address is in the correct format. Meanwhile, <code>sanitizeInput()</code> escapes HTML tags to prevent XSS attacks.</p>
<h2 id="heading-secure-communication-and-https">Secure Communication and HTTPS</h2>
<p>Securing communication between clients and servers is imperative to protect sensitive data. Enabling HTTPS (HTTP Secure) ensures encrypted data transmission over the network.</p>
<p>In Kotlin server applications, configuring HTTPS can be achieved using Ktor:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> io.ktor.server.engine.embeddedServer
<span class="hljs-keyword">import</span> io.ktor.server.netty.Netty
<span class="hljs-keyword">import</span> io.ktor.features.HSTS
<span class="hljs-keyword">import</span> io.ktor.features.HttpsRedirect

<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> server = embeddedServer(Netty, port = <span class="hljs-number">8080</span>) {
        install(HttpsRedirect) {
            sslPort = <span class="hljs-number">8443</span>
        }
        install(HSTS) {
            includeSubDomains = <span class="hljs-literal">true</span>
        }
    }
    server.start(wait = <span class="hljs-literal">true</span>)
}
</code></pre>
<p>In this example, Ktor's HttpsRedirect feature redirects HTTP requests to HTTPS, ensuring secure communication.</p>
<p>Make sure your project has the necessary Ktor dependencies and that you've imported the required features (HSTS and HttpsRedirect) to use these functionalities.</p>
<p>If you encounter errors with the code, make sure that you've included the appropriate Ktor dependencies in your project's build file (for example, <code>build.gradle.kts</code> or <code>pom.xml</code> for Gradle or Maven respectively) and have updated your project to resolve these dependencies.</p>
<h2 id="heading-handling-security-headers-and-csrf-protection">Handling Security Headers and CSRF Protection</h2>
<p>Security headers play a vital role in mitigating various web vulnerabilities. Configuring headers like Content Security Policy (CSP), X-Frame-Options, and others is essential in Kotlin server applications to enhance security.</p>
<p>Let's implement security headers using Ktor:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> io.ktor.application.*
<span class="hljs-keyword">import</span> io.ktor.features.*

<span class="hljs-function"><span class="hljs-keyword">fun</span> Application.<span class="hljs-title">installSecurityHeaders</span><span class="hljs-params">()</span></span> {
    install(DefaultHeaders)
    install(ContentNegotiation)
    install(Compression)
    install(CachingHeaders)
    install(XForwardedHeaderSupport)
    install(FrameOptions) {
        frameOptionsHeader = <span class="hljs-string">"DENY"</span>
    }
    install(ContentSecurityPolicy) {
        default {
            frameAncestors {
                self
            }
            script {
                unsafeInline = ContentSecurityPolicyHeader.UnsafeInlineSource
            }
        }
    }
}
</code></pre>
<p>Here, we use Ktor's ContentSecurityPolicy and FrameOptions features to define security headers like Content Security Policy and X-Frame-Options, mitigating potential risks like clickjacking attacks.</p>
<h2 id="heading-logging-and-monitoring-for-security">Logging and Monitoring for Security</h2>
<p>Comprehensive logging is crucial for detecting security incidents and analyzing application behaviour. Logging security-related events and suspicious activities helps you identify potential threats in Kotlin server applications.</p>
<p>Let's implement logging using the Logback logging framework in Kotlin:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> org.slf4j.LoggerFactory

<span class="hljs-keyword">val</span> logger = LoggerFactory.getLogger(<span class="hljs-string">"SecurityLogger"</span>)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">logSecurityEvent</span><span class="hljs-params">(event: <span class="hljs-type">String</span>)</span></span> {
    logger.info(<span class="hljs-string">"Security event: <span class="hljs-variable">$event</span>"</span>)
}
</code></pre>
<p>In this example, we've created a SecurityLogger instance using Logback to record security events such as authentication failures or access denied attempts.</p>
<h2 id="heading-securing-dependencies-and-patch-management">Securing Dependencies and Patch Management</h2>
<p>Maintaining the security of dependencies within Kotlin projects is fundamental to preempting vulnerabilities introduced by third-party libraries. Regularly updating and managing dependencies is critical to addressing potential security flaws that could compromise the application's integrity.</p>
<p>To ensure the security of dependencies, it's vital to employ best practices such as version pinning and utilizing tools like Gradle or Maven.</p>
<h3 id="heading-version-pinning">Version Pinning</h3>
<p>Defining specific versions of dependencies in project configuration files (like <code>build.gradle.kts</code> for Gradle or <code>pom.xml</code> for Maven) ensures that known vulnerabilities are patched. By explicitly specifying versions, developers can control which libraries and versions their project utilizes, minimizing exposure to security risks associated with outdated or vulnerable dependencies.</p>
<h3 id="heading-dependency-update-automation">Dependency Update Automation</h3>
<p>Leveraging automated tools or services that periodically scan for dependency updates and security vulnerabilities (for example Dependabot, Renovate) can significantly streamline the process of managing dependencies. These tools automatically identify outdated dependencies and suggest updated versions or patches, simplifying the task of keeping dependencies secure and up-to-date.</p>
<p>In Kotlin projects, managing dependencies securely involves explicitly declaring libraries and versions in build configuration files:</p>
<p>Gradle (build.gradle.kts):</p>
<pre><code class="lang-kotlin">dependencies {
    implementation(<span class="hljs-string">"org.jetbrains.kotlin:kotlin-stdlib:1.6.0"</span>)
}
</code></pre>
<p>Maven (pom.xml):</p>
<pre><code class="lang-kotlin">&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.jetbrains.kotlin&lt;/groupId&gt;
        &lt;artifactId&gt;kotlin-stdlib&lt;/artifactId&gt;
        &lt;version&gt;<span class="hljs-number">1.6</span><span class="hljs-number">.0</span>&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!-- Add other dependencies securely and define versions --&gt;
&lt;/dependencies&gt;
</code></pre>
<p>By employing these practices and utilizing tools that aid in dependency analysis and updates, Kotlin projects can maintain a more robust and secure ecosystem, mitigating the risks associated with outdated or vulnerable dependencies.</p>
<h2 id="heading-testing-and-secure-development-practices">Testing and Secure Development Practices</h2>
<p>Security testing plays a pivotal role in identifying vulnerabilities within Kotlin server applications. Adopting various testing methodologies helps in detecting and rectifying security flaws early in the development lifecycle.</p>
<h3 id="heading-penetration-testing">Penetration Testing:</h3>
<p>Performing penetration tests involves simulating attacks to assess the system's security posture. Tools like OWASP ZAP or Burp Suite assist in identifying potential vulnerabilities like SQL injection, XSS, or CSRF.</p>
<h3 id="heading-vulnerability-scanning">Vulnerability Scanning:</h3>
<p>Automated vulnerability scanning tools, such as Nessus or OpenVAS, can help you identify security weaknesses within the application and its dependencies. These tools scan for known vulnerabilities, outdated libraries, or misconfigurations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Throughout this guide, we've explored diverse security measures tailored for Kotlin server applications. From authentication mechanisms to securing communication, input validation, and compliance considerations, each aspect contributes significantly to fortifying the application against potential threats.</p>
<p>Ensuring the security of Kotlin server applications is an ongoing endeavour. It's crucial to emphasize the need for continuous vigilance, proactive monitoring, and a proactive approach to address evolving security challenges.</p>
<p>To create secure Kotlin applications, you must adopt a security-first mindset. Prioritizing security considerations at every stage of the development lifecycle helps in crafting robust and trustworthy server applications.</p>
<p>By implementing the best practices discussed in this guide and staying updated on emerging security trends, you can significantly enhance the security of your server applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Kotlin and Android Development – Build a Chat App ]]>
                </title>
                <description>
                    <![CDATA[ Are you ready to dive into the world of Android development using Kotlin? We just posted a 10-hour Android course on the freeCodeCamp.org YouTube channel. Alexandru Cristian created this course. I will help you understand how to develop with Kotlin a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/kotlin-and-android-development-build-a-chat-app/</link>
                <guid isPermaLink="false">66b203db82069b4c678c98e7</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 30 Oct 2023 16:24:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/kotlinandroid.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you ready to dive into the world of Android development using Kotlin?</p>
<p>We just posted a 10-hour Android course on the freeCodeCamp.org YouTube channel. Alexandru Cristian created this course. I will help you understand how to develop with Kotlin and Android.</p>
<p>This course will take you on a journey through:</p>
<ul>
<li>Collections such as lists, sets, and maps</li>
<li>Generics and type parameters</li>
<li>Lambda functions and scope functions</li>
<li>Android Studio, its file structure, and XML design</li>
<li>Android widgets like buttons, TextView, EditText, and more</li>
<li>How to build a fully functional quiz application for Android devices.</li>
</ul>
<p>The course is divided into several chapters, each focused on a specific topic, to provide a structured learning experience. Here's a glimpse of the chapters included in the course:</p>
<ol>
<li>Introduction</li>
<li>List, Set, Map</li>
<li>Mapping</li>
<li>Zipping and Association</li>
<li>Flatten</li>
<li>String Representation</li>
<li>Filtering</li>
<li>Test predicates - any(), none(), all()</li>
<li>Plus and Minus Operators</li>
<li>Grouping</li>
<li>Retrieve Collections Parts</li>
<li>Retrieve Single Elements</li>
<li>Aggregate Operations - sum(), count(), average(), minOrNull(), maxOrNull()</li>
<li>Comparable and Comparator</li>
<li>Binary Search</li>
<li>Generics - Type Parameters and Casting</li>
<li>Generics - Upper Bounds</li>
<li>Generics - Covariance and Contravariance</li>
<li>Generics - Type Erasure and reified keyword</li>
<li>Generics - Where keyword; and 2 Upper Bounds</li>
<li>Access Modifiers</li>
<li>Packages and Imports</li>
<li>Exceptions - Try Catch, Finally</li>
<li>Lambda Functions</li>
<li>Lambdas - it modifier</li>
<li>Scope Functions</li>
<li>Download Android Studio</li>
<li>Android Studio Presentation</li>
<li>Android File Structure</li>
<li>Android XML and Design</li>
<li>Android XML properties</li>
<li>Android - what does findViewById() function do?</li>
<li>String XML</li>
<li>Android Manifest</li>
<li>Android Button and TextView</li>
<li>Android Button OnClickListener</li>
<li>Android EditText</li>
<li>Android App - Convert Inches</li>
<li>Android App - Convert Inches 2</li>
<li>Android App - Change Color</li>
<li>Android Radio Buttons 1</li>
<li>Android Radio Buttons 2</li>
<li>Android SeekBar</li>
<li>Android Toggle Button</li>
<li>Quiz App - UI Welcome Screen</li>
<li>Quiz App - Creating Question Model</li>
<li>Quiz App - Setting the QuizActivity</li>
<li>Quiz App - Connecting the UI with the model</li>
<li>Quiz App - Adding the Button functionality</li>
<li>Quiz App - Selecting the Right and Wrong answers</li>
<li>Quiz App - Setting up the UI for ResultActivity</li>
<li>Quiz App - Improve Code</li>
<li>Quiz App - Sending data to Result Activity</li>
<li>Quiz App - Solve score bug</li>
</ol>
<p>This course is designed to give you a holistic understanding of Kotlin and Android development, with hands-on examples and real-world applications.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/kNghEbknLs8">the freeCodeCamp.org YouTube channel</a> (10-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/kNghEbknLs8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Kotlin VS Java – What's the Difference? ]]>
                </title>
                <description>
                    <![CDATA[ By Shittu Olumide Technology advances very quickly these days, and there's always a new programming language or tool to learn.  You may have heard developers discussing the merits of and differences between two popular programming languages – Java an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/kotlin-vs-java/</link>
                <guid isPermaLink="false">66d461177df3a1f32ee7f89e</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 08 May 2023 13:48:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/Shittu-Olumide-Kotlin-VS-Java---What-s-the-Difference.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shittu Olumide</p>
<p>Technology advances very quickly these days, and there's always a new programming language or tool to learn. </p>
<p>You may have heard developers discussing the merits of and differences between two popular programming languages – Java and Kotlin. </p>
<p>So what's the difference between them? Which one should you learn? Well, you are in the right place, because that's what we'll talk about in this guide. I'll highlight the major differences between Java and Kotlin that you need to know in a very simple way.</p>
<h2 id="heading-overview-of-kotlin-and-java">Overview of Kotlin and Java</h2>
<p>Kotlin and Java are two popular programming languages used to build software applications for a variety of platforms. While Java has been a dominant language in the software industry for over two decades, Kotlin is a newer language that has gained popularity in recent years due to its modern features and seamless interoperability with Java.</p>
<p>Java was first released in 1995 by Sun Microsystems, and it quickly became a popular language for building enterprise software applications. It is an object-oriented language with a strong emphasis on readability, maintainability, and portability. </p>
<p>Java is platform-independent, which means that it can be compiled and run on any platform that has a Java Virtual Machine (JVM).</p>
<p>Kotlin, on the other hand, was created by JetBrains in 2011 as an alternative to Java. It is a modern, statically-typed programming language that runs on the JVM, Android, and can be compiled to JavaScript. </p>
<p>Kotlin is designed to be concise, safe, and interoperable with Java, making it easy to integrate into existing Java projects.</p>
<p>In recent years, Kotlin has gained significant traction in the developer community, with many companies and organizations adopting it as their primary language for building software applications. But Java still remains a popular choice for building enterprise software, and it is likely to continue to be used for many years to come.</p>
<h2 id="heading-differences-between-kotlin-and-java">Differences Between Kotlin and Java</h2>
<p>In this section, we will examine the key differences between these two programming languages.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Kotlin</strong></td><td><strong>Java</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Syntax</strong></td><td>More concise and expressive syntax</td><td>More verbose syntax</td></tr>
<tr>
<td><strong>Null safety</strong></td><td>Built-in null safety features</td><td>No built-in null safety features</td></tr>
<tr>
<td><strong>Interoperability</strong></td><td>Seamless interoperability with Java</td><td>Interoperable, but requires extra work</td></tr>
<tr>
<td><strong>Extension functions</strong></td><td>Supports extension functions</td><td>No support for extension functions</td></tr>
<tr>
<td><strong>Lambdas</strong></td><td>More concise and expressive syntax for lambdas</td><td>Lambdas are verbose and require more code</td></tr>
<tr>
<td><strong>IDE support</strong></td><td>Strong IDE support in IntelliJ IDEA    Strong</td><td>IDE support in multiple IDEs</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Comparable performance to Java</td><td>High performance, especially for large-scale applications</td></tr>
<tr>
<td><strong>Learning curve</strong></td><td>Can have a steeper learning curve for those familiar with Java</td><td>Fairly intuitive to learn</td></tr>
<tr>
<td><strong>Community support</strong></td><td>Growing community with increasing resources</td><td>Large and established community with a wealth of resources</td></tr>
<tr>
<td><strong>Build tools</strong></td><td>Uses Gradle as the default build tool</td><td>Uses Maven as the default build tool</td></tr>
</tbody>
</table>
</div><p>It's important to note that this is not an exhaustive list, and there are other differences between Kotlin and Java depending on your specific use case. But this table provides some of the key differences between the two technologies.</p>
<h3 id="heading-code-examples-of-differences-between-kotlin-and-java">Code examples of differences between Kotlin and Java</h3>
<p>To write a Lambda Expression in Kotlin looks like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> list = listOf(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>)
<span class="hljs-keyword">val</span> evenNumbers = list.filter { it % <span class="hljs-number">2</span> == <span class="hljs-number">0</span> }
</code></pre>
<p>But in Java, it is much more verbose:</p>
<pre><code class="lang-java">List&lt;Integer&gt; list = Arrays.asList(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>);
List&lt;Integer&gt; evenNumbers = list.stream()
                                 .filter(n -&gt; n % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>)
                                 .collect(Collectors.toList());
</code></pre>
<p>Another practical example is using Extension Functions.</p>
<p>Kotlin allows you to add new functions to existing classes using extension functions:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> String.<span class="hljs-title">isPalindrome</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> == <span class="hljs-keyword">this</span>.reversed()
}
</code></pre>
<p>In Java, you cannot define extension functions. Instead, you can create utility classes with static methods:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StringUtils</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isPalindrome</span><span class="hljs-params">(String str)</span> </span>{
        <span class="hljs-keyword">return</span> str.equals(<span class="hljs-keyword">new</span> StringBuilder(str).reverse().toString());
    }
}
</code></pre>
<h2 id="heading-use-cases-for-kotlin-and-java">Use Cases for Kotlin and Java</h2>
<p>Both Kotlin and Java have their own unique use cases and when it is most suitable to use either of them.</p>
<h3 id="heading-when-to-use-kotlin">When to use Kotlin:</h3>
<ul>
<li><strong>Android app development</strong>: Kotlin is the recommended language for developing Android apps by Google. It offers features like null safety, concise code, and better readability, making it easier to build and maintain Android applications.</li>
<li><strong>Web development</strong>: you can also use Kotlin for server-side development, and it can run on the Java Virtual Machine (JVM). This makes it a great choice for building web applications, especially when you need interoperability with Java.</li>
<li><strong>Data science and machine learning</strong>: Kotlin has recently gained popularity in the field of data science and machine learning due to its ability to integrate well with Python libraries, such as TensorFlow and PyTorch.</li>
<li><strong>Cross-platform development</strong>: you can use Kotlin to build applications for multiple platforms, including desktop, mobile, and web. This makes it an attractive choice for developers who want to build applications that can run on multiple devices.</li>
</ul>
<h3 id="heading-when-to-use-java">When to use Java:</h3>
<ul>
<li><strong>Enterprise application development</strong>: Java has been the go-to language for enterprise application development for decades. It has a vast ecosystem of libraries and frameworks you can use to build complex enterprise applications.</li>
<li><strong>Legacy systems</strong>: Many legacy systems are built on Java, and migrating them to a new language may not be feasible or cost-effective. In these cases, Java is still the best choice for maintaining and updating these systems.</li>
<li><strong>High-performance applications</strong>: Java is known for its performance and scalability, and it is often used for building high-performance applications that require high throughput and low latency.</li>
<li><strong>Android app development</strong>: While Kotlin is now the recommended language for Android app development, Java is still a viable option. Many existing Android apps are built on Java, and you can still use it to build new applications for the platform.</li>
<li><strong>Large-scale projects</strong>: Java's strong type system and emphasis on maintainability and scalability make it an ideal choice for large-scale projects. Its modular architecture also makes it easier to manage and maintain large codebases.</li>
<li><strong>Desktop application development</strong>: you can use Java to build cross-platform desktop applications, making it a good choice for developers who want to build applications that can run on multiple operating systems.</li>
<li><strong>Financial applications</strong>: Java's security features and stability make it a popular choice for building financial applications that require high levels of security and reliability.</li>
<li><strong>Gaming</strong>: Java can also be used for game development, especially for browser-based games. It has a built-in 2D and 3D graphics engine that makes it easy to create games that run on multiple platforms.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, Kotlin and Java are both powerful programming languages with their own unique strengths and use cases. </p>
<p>Kotlin is a relatively new language that offers features like null safety, concise code, and better readability, making it a great choice for Android app development, web development, data science, and cross-platform development. </p>
<p>Java, on the other hand, has been around for decades and is the go-to language for enterprise application development, legacy systems, high-performance applications, desktop application development, financial applications, and gaming.</p>
<p>If you're building an Android app, Kotlin is the recommended language by Google. If you're working on a legacy system or an enterprise application, Java is likely the best choice. </p>
<p>Finally, it's worth noting that Kotlin and Java are not mutually exclusive, and in many cases, they can be used together to achieve the best of both worlds.</p>
<p>Let's connect on <a target="_blank" href="https://www.twitter.com/Shittu_Olumide_">Twitter</a> and on <a target="_blank" href="https://www.linkedin.com/in/olumide-shittu">LinkedIn</a>. You can also subscribe to my <a target="_blank" href="https://www.youtube.com/channel/UCNhFxpk6hGt5uMCKXq0Jl8A">YouTube</a> channel.</p>
<p>Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Kotlin VS Java – What's the Difference? ]]>
                </title>
                <description>
                    <![CDATA[ Java is a widely popular programming language that has been used for years in various domains, including web development, mobile app development, desktop applications, and game development.  On the other hand, Kotlin is a relatively new programming l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/kotlin-vs-java-whats-the-difference/</link>
                <guid isPermaLink="false">66c8c870fe21816c4cb75d09</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Israel Chidera ]]>
                </dc:creator>
                <pubDate>Fri, 31 Mar 2023 20:21:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/emile-perron-xrVDYZRGdw4-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Java is a widely popular programming language that has been used for years in various domains, including web development, mobile app development, desktop applications, and game development. </p>
<p>On the other hand, Kotlin is a relatively new programming language that has been gaining popularity in recent years. Both languages are used to build applications for the Java Virtual Machine (JVM), but they differ in terms of syntax, features, and performance. </p>
<p>Java has been around for quite some time and has a vast community and a plethora of libraries. On the other hand, Kotlin is a relatively new language that offers contemporary features and concise syntax, which makes it an appealing alternative for developers. </p>
<p>In this article, we will discuss the differences between Kotlin and Java.</p>
<h1 id="heading-differences-between-kotlin-and-java">Differences Between Kotlin and Java</h1>
<h2 id="heading-syntax">Syntax</h2>
<p>One of the most significant differences between Kotlin and Java is the syntax. Kotlin has a more concise syntax than Java, which means that it requires less code to perform the same operations. </p>
<p>For example, let's compare the syntax for creating a class in both languages:</p>
<pre><code class="lang-java"><span class="hljs-comment">//java</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
   <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> myField;

   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> myField)</span> </span>{
      <span class="hljs-keyword">this</span>.myField = myField;
   }

   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getMyField</span><span class="hljs-params">()</span> </span>{
      <span class="hljs-keyword">return</span> myField;
   }

   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMyField</span><span class="hljs-params">(<span class="hljs-keyword">int</span> myField)</span> </span>{
      <span class="hljs-keyword">this</span>.myField = myField;
   }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-comment">//kotlin</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> myField: <span class="hljs-built_in">Int</span>) {
   <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getMyField</span><span class="hljs-params">()</span></span> = myField
   <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setMyField</span><span class="hljs-params">(value: <span class="hljs-type">Int</span>)</span></span> { myField = value }
}
</code></pre>
<p>As you can see, the Kotlin version is much more concise and readable than the Java version. In Kotlin, we can define the class and its fields in a single line, and the getters and setters are replaced with property accessors.</p>
<p>Additionally, Kotlin supports type inference, which means that you do not have to specify the data type of a variable explicitly.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//kotlin</span>

<span class="hljs-keyword">val</span> myString = <span class="hljs-string">"Hello, world!"</span>
</code></pre>
<p>As seen in the Kotlin code above, we can use type inference to declare a variable without explicitly specifying its data type. The compiler will automatically determine the data type based on the value that we assign to the variable. This can make our code more concise and easier to read.</p>
<pre><code class="lang-java"><span class="hljs-comment">//java</span>

String myString = <span class="hljs-string">"Hello, world!"</span>;
</code></pre>
<p>In the Java code above, you are required to specify the data type of the variable which can make your code more verbose.</p>
<p>Here is another example showing the difference between the verbose syntax of Java and a more concise Kotlin syntax.</p>
<pre><code class="lang-java"><span class="hljs-comment">//java</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloWorld</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        System.out.println(<span class="hljs-string">"Hello, World!"</span>);
    }
}
</code></pre>
<p>The code above is a simple "Hello, World!" program in Java that prints “Hello, World!” to the console.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//kotlin</span>

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Hello, World!"</span>)
}
</code></pre>
<p>As you can see, the Kotlin version is much shorter and more expressive. Kotlin achieves this by eliminating unnecessary boilerplate code, such as type declarations and semicolons, and using more natural language constructs.</p>
<h2 id="heading-null-safety">Null Safety</h2>
<p>Both Kotlin and Java compile to bytecode that runs on the JVM, which means they have similar performance characteristics. </p>
<p>But Kotlin has some performance advantages over Java in certain cases. For example, Kotlin's <strong>null safety</strong> feature can help reduce the number of runtime exceptions and improve the overall performance of the application. And Kotlin's use of immutable data structures can also lead to improved performance.</p>
<p><strong>Null safety</strong> is another area where Kotlin differs from Java. In Java, it's possible to have null values assigned to a variable, which can lead to null pointer exceptions at runtime. Kotlin, on the other hand, requires you to explicitly define whether a variable can be null or not. This makes it easier to avoid null pointer exceptions during runtime. </p>
<p>For example, in Kotlin, all variables are non-null by default, meaning that they cannot hold a null value unless explicitly declared as nullable using the "?" operator. This helps to prevent null-related errors at compile-time, rather than waiting until runtime.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//kotlin</span>

<span class="hljs-keyword">var</span> name: String = <span class="hljs-string">"John"</span> <span class="hljs-comment">// non-null variable</span>
<span class="hljs-keyword">var</span> age: <span class="hljs-built_in">Int</span>? = <span class="hljs-literal">null</span> <span class="hljs-comment">// nullable variable</span>
</code></pre>
<h2 id="heading-functional-programming">Functional Programming</h2>
<p>Another significant difference between Java and Kotlin is their support for functional programming. While Java has added some support for functional programming in recent years with the release of <strong>Java 8</strong>, Kotlin was designed from the ground up to support functional programming concepts.</p>
<p>For example, Kotlin supports lambda expressions, higher-order functions, and extension functions. These features make it easier to write code that is both concise and expressive and can help to improve code quality. Here is a code sample showing this:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//kotlin</span>
<span class="hljs-comment">// lambda expression</span>
<span class="hljs-keyword">val</span> list = listOf(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
<span class="hljs-keyword">val</span> doubledList = list.map { it * <span class="hljs-number">2</span> }

<span class="hljs-comment">// higher-order function</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">higherOrderFunc</span><span class="hljs-params">(x: <span class="hljs-type">Int</span>, y: <span class="hljs-type">Int</span>, f: (<span class="hljs-type">Int</span>, <span class="hljs-type">Int</span>) -&gt; <span class="hljs-type">Int</span>)</span></span>: <span class="hljs-built_in">Int</span> {
    <span class="hljs-keyword">return</span> f(x, y)
}
<span class="hljs-keyword">val</span> result = higherOrderFunc(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>) { x, y -&gt; x + y }

<span class="hljs-comment">// extension function</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-built_in">Int</span>.<span class="hljs-title">isEven</span><span class="hljs-params">()</span></span> = <span class="hljs-keyword">this</span> % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>
<span class="hljs-keyword">val</span> isFourEven = <span class="hljs-number">4</span>.isEven()
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, <strong>Kotlin</strong> and <strong>Java</strong> are both awesome programming languages that have some significant differences. While Java is a more established language with a large community and extensive libraries, Kotlin provides modern features and concise syntax, making it an attractive choice for many developers. </p>
<p>Kotlin's focus on null safety and support for functional programming make it well-suited for modern application development, while Java's performance and library ecosystem make it a good choice for enterprise applications. </p>
<p>Ultimately, the choice between Java and Kotlin will depend on the specific needs of your application and your development team's preferences and skills.  </p>
<p>I hope this article was informative.<br>Happy learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Serialize Your Data in Kotlin and Jetpack Compose ]]>
                </title>
                <description>
                    <![CDATA[ Serialization is the process of transforming data that's in one format into another format that can be stored.  If you have ever worked with a database or fetching data from a server, this should all be familiar to you. If not, you have come to the r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/serializing-your-data-in-kotlin/</link>
                <guid isPermaLink="false">66ba503a158e6c6a8cb8c7a5</guid>
                
                    <category>
                        <![CDATA[ Jetpack Compose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tomer ]]>
                </dc:creator>
                <pubDate>Wed, 01 Feb 2023 21:19:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/fineas-anton-cnoMG2034k8-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Serialization is the process of transforming data that's in one format into another format that can be stored. </p>
<p>If you have ever worked with a database or fetching data from a server, this should all be familiar to you. If not, you have come to the right place. </p>
<p>In this tutorial, we will go over:</p>
<ul>
<li>How to setup serialization in a Jetpack Compose project</li>
<li>How to serialize a data class</li>
<li>How to de-serialize a data class</li>
</ul>
<p>You might be asking yourself, what’s so special about serialization in Jetpack Compose? In essence, there isn’t a lot of difference than with a regular Kotlin Android project. The only difference is in the setup.</p>
<h2 id="heading-how-to-set-everything-up">How to Set Everything Up</h2>
<p>Each version of Jetpack Compose corresponds with a version of Kotiln that it is compatible with. Each version of the kotlin-serialization library is also compatible with a specific version of Kotlin. So you need to make sure that each of the three parts in this tripod are compatible with one another.</p>
<p>How can you that?</p>
<p>Your first resource you'll want to consult is the <a target="_blank" href="https://developer.android.com/jetpack/androidx/releases/compose-kotlin">Compose to Kotlin Compatibility Map</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/1_5brVwILW54aNaFFimDF87Q.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here you can see which version of Jetpack Compose corresponds to which Kotlin version.</p>
<p>The second resource you will need is the <a target="_blank" href="https://github.com/Kotlin/kotlinx.serialization/releases">releases page</a> for the kotlin-serialization library. There you will find which library version is compatible with which Kotlin version.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/1_y6Ba1fROOcSSXXm-Nll4Ew.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Confused? 😕</p>
<p>Let’s illustrate this with an example:</p>
<ul>
<li>Your Jetpack Compose version is <strong>1.1.0</strong>.</li>
<li>Looking over the compatibility map, you see it is compatible with Kotlin version <strong>1.6.10</strong>.</li>
<li>Heading to the releases page of kotlin-serialization library, you see that the version of the kotlin-serialization library that you need to use is <strong>1.3.2</strong>.</li>
</ul>
<p>Head into your project level build.gradle file, and inside the buildscript object, in the dependencies section, put in classpath for the kotlin-serialization library with the version you need.</p>
<pre><code class="lang-kotlin">dependencies {
        ...
        classpath <span class="hljs-string">"org.jetbrains.kotlin:kotlin-serialization:X.Y.Z"</span>
 }
</code></pre>
<p>Then, head over to your application build.gradle file and do these two things:</p>
<ol>
<li>Add the <strong>id ‘org.jetbrains.kotlin.plugin.serialization’</strong> inside of the plugins at the top of the file:</li>
</ol>
<pre><code class="lang-kotlin">plugins {
   ...
   id <span class="hljs-string">'org.jetbrains.kotlin.plugin.serialization'</span>
}
</code></pre>
<ol start="2">
<li>At the bottom of the file, inside the dependencies section add <strong>implementation ‘org.jetbrains.kotlinx:kotlinx-serialization-json:X.Y.Z’</strong>:</li>
</ol>
<pre><code class="lang-kotlin">dependencies {
   ...
   implementation <span class="hljs-string">'org.jetbrains.kotlinx:kotlinx-serialization-json:X.Y.Z'</span>
}
</code></pre>
<p>Sync your project and you should be good to go.</p>
<p>Note that we are using the <strong>json</strong> format of the library, but there are other formats that are supported as well:</p>
<ul>
<li>Protocol Buffers</li>
<li>CBOR (Concise Binary Object Representation)</li>
<li>Properties</li>
<li>HOCON (Human Optimized Config Object Notation)</li>
</ul>
<blockquote>
<p>⚠️ If you encounter any errors, make sure the versions you put are correct</p>
</blockquote>
<h2 id="heading-how-to-build-your-data-class">How to Build Your Data Class</h2>
<p>In order to have something we can serialize and later de-serialize, we need to work with data classes. </p>
<p>Creating a data class is simple. If you are using Android Studio, just right click inside your project’s module and choose New Kotlin file. Enter your class name and then append the data keyword before it.</p>
<p>For the sake of this article, let's say we are working with an API that returns a list of users. Each user object has a range of attributes it can have (just to name a few):</p>
<ul>
<li>First name</li>
<li>Last name</li>
<li>Age</li>
<li>Birthdate</li>
<li>Id</li>
</ul>
<p>To make our data class serializable, all you need to do is add the <strong>@Serializable</strong> annotation above the class declaration.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Serializable</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span></span>(
   <span class="hljs-keyword">val</span> firstName: String,
   <span class="hljs-keyword">val</span> lastName: String,
   <span class="hljs-keyword">val</span> age: <span class="hljs-built_in">Int</span>,
   <span class="hljs-keyword">val</span> birthdate: Date,
   <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Long</span>
)
</code></pre>
<p>Pretty nifty, right?</p>
<p>Well, there’s more.</p>
<p>The variable that will hold the user’s first name is written as firstName. That means that in the response from our server, it needs to return in a field with the same name. </p>
<p>Sometimes, in API responses, the keys are not written in camelCase, but rather in kebab_case. That would mean that the key for first name, might be first_name. In that case, we would have to write it out like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Serializable</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span></span>(
   <span class="hljs-keyword">val</span> first_name: String,
   <span class="hljs-keyword">val</span> lastName: String,
   <span class="hljs-keyword">val</span> age: <span class="hljs-built_in">Int</span>,
   <span class="hljs-keyword">val</span> birthdate: Date,
   <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Long</span>
)
</code></pre>
<p>But that is not the <a target="_blank" href="https://kotlinlang.org/docs/coding-conventions.html">convention</a> for property names in Kotlin.</p>
<p>So what can we do?</p>
<p>We can use the <strong>@SerialName</strong> annotation. This allows us to mark what the name of the field will be from the response and then write anything as the property for it.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Serializable</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span></span>(
   <span class="hljs-meta">@SerialName(<span class="hljs-meta-string">"first_name"</span>)</span>
   <span class="hljs-keyword">val</span> firstName: String,
   <span class="hljs-keyword">val</span> lastName: String,
   <span class="hljs-keyword">val</span> age: <span class="hljs-built_in">Int</span>,
   <span class="hljs-keyword">val</span> birthdate: Date,
   <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Long</span>
)
</code></pre>
<h2 id="heading-how-to-serialize-and-de-serialize">How to Serialize and De-Serialize</h2>
<p>Now that our data class is set up, let’s enjoy the fruits of our labor. Whenever we need to serialize our data class, we will use the <a target="_blank" href="https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/encode-to-string.html">Json.encodeToString</a> method:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> dataAsString: String = Json.encodeToString(user)
</code></pre>
<p>When we run the above line of code, we will get our data class in string form.</p>
<p>De-serializing our data is as simple as serializing it. We will use the <a target="_blank" href="https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/decode-from-string.html">Json.decodeFromString</a> method:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> user: UserModel = Json.decodeFromString&lt;UserModel&gt;(dataAsString)
</code></pre>
<blockquote>
<p>✋ Notice that we specified which type of data we want to de-serialize to with the type parameter ().</p>
</blockquote>
<p><img src="https://images.unsplash.com/photo-1600176842064-635fe81d2441?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDMwfHxyZW1vdGUlMjBjb250cm9sfGVufDB8fHx8MTY3NTAxODM0NQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Image" width="2000" height="1325" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@macroman?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Immo Wegmann / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>Time for some extra credit.</p>
<p>Let’s say that in your data class you have a field that you don’t want to serialize. If we take our UserModel class, imagine that we want to have a user’s actual picture (bitmap).</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Serializable</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span></span>(
   <span class="hljs-meta">@SerialName(<span class="hljs-meta-string">"first-name"</span>)</span>
   <span class="hljs-keyword">val</span> firstName: String,
   <span class="hljs-keyword">val</span> lastName: String,
   <span class="hljs-keyword">val</span> age: <span class="hljs-built_in">Int</span>,
   <span class="hljs-keyword">val</span> birthdate: Date,
   <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Long</span>,
   <span class="hljs-keyword">var</span> photo: Bitmap?
)
</code></pre>
<p>This is not something we will get from our API call, so how can we exclude it? Because if we don’t, our serialization will fail.</p>
<p>Here to our rescue is the <a target="_blank" href="https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-transient/"><strong>@Transient</strong> annotation</a>.</p>
<pre><code>@Serializable
data <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span>(
   @<span class="hljs-title">SerialName</span>("<span class="hljs-title">first</span>-<span class="hljs-title">name</span>")
   <span class="hljs-title">val</span> <span class="hljs-title">firstName</span>: <span class="hljs-title">String</span>,
   <span class="hljs-title">val</span> <span class="hljs-title">lastName</span>: <span class="hljs-title">String</span>,
   <span class="hljs-title">val</span> <span class="hljs-title">age</span>: <span class="hljs-title">Int</span>,
   <span class="hljs-title">val</span> <span class="hljs-title">birthdate</span>: <span class="hljs-title">Date</span>,
   <span class="hljs-title">val</span> <span class="hljs-title">id</span>: <span class="hljs-title">Long</span>,
   @<span class="hljs-title">Transient</span>
   <span class="hljs-title">var</span> <span class="hljs-title">photo</span>: <span class="hljs-title">Bitmap</span>?
)</span>
</code></pre><p>This will exclude the marked field from being serialized and de-serialized.</p>
<ul>
<li>If you want to see a real life example of using serialization inside a project, you can check out a project I made <a target="_blank" href="https://medium.com/r?url=https%3A%2F%2Fgithub.com%2FTomerPacific%2Fmovies-presenter">here</a></li>
<li>And if you would like to read other articles I have written, you can go <a target="_blank" href="https://medium.com/r?url=https%3A%2F%2Fgithub.com%2FTomerPacific%2FMediumArticles">here</a></li>
<li>For more information about the kotlin-serialization library, you can go <a target="_blank" href="https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/basic-serialization.md#json-encoding">here</a></li>
</ul>
<p>Thank you for reading! Happy serializing.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Abstraction in Programming? Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ This article will not be a dry and boring explanation of abstract classes, interfaces, protocols, or similar software entities. I will explain what they are in simple terms, but my main goal is to change how you think about abstractions in general. A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-abstraction-in-programming-for-beginners/</link>
                <guid isPermaLink="false">66d460d3c7632f8bfbf1e49d</guid>
                
                    <category>
                        <![CDATA[ abstraction ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Wed, 21 Dec 2022 18:08:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/smartphone-g7993a9917_1280-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This article will not be a dry and boring explanation of abstract classes, interfaces, protocols, or similar software entities.</p>
<p>I will explain what they are in simple terms, but my main goal is to change how you think about abstractions in general. All of this is in service of helping you develop the art of programming.</p>
<p>These are the topics I will cover:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-an-abstraction">What is an abstraction?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-abstractions-in-your-programs">How to use abstractions in your programs</a><br>  – <a class="post-section-overview" href="#heading-how-to-use-interfaces-and-protocols">How to use interfaces and protocols</a><br>  – <a class="post-section-overview" href="#heading-how-to-use-function-types-and-lambda-expressions">How to use function types and lambda expressions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-is-abstraction-the-most-important-idea-in-programming">Is abstraction the most important idea in programming?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-much-abstraction-do-i-need">How much abstraction do I need?</a></p>
</li>
</ul>
<p>The code samples will be in Kotlin, but I have written the article assuming you only have basic programming knowledge in any industry standard language.</p>
<p>I also use a variety of approaches to cover both object-oriented and functional styles of code.</p>
<h2 id="heading-what-is-an-abstraction">What Is An Abstraction?</h2>
<p>To begin with, we will discuss what this term means in the most general sense. Here is a simplified definition I have come up with for an abstraction:</p>
<blockquote>
<p>“A <strong>less detailed representation</strong> of an object or concept in nature.”</p>
</blockquote>
<p>I know my definition sounds very vague, but we will discuss some clear examples shortly. First, we must understand what <strong>detail</strong> is.</p>
<h3 id="heading-what-is-detail">What Is Detail?</h3>
<p>Detail refers to the quantity, or density perhaps, of information. Here are two examples of data models which are more and less detailed:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">User</span> {
  <span class="hljs-type">name</span>,
  id
}
</code></pre>
<pre><code class="lang-pgsql"><span class="hljs-keyword">User</span> {
  <span class="hljs-type">name</span>: String,
  id: <span class="hljs-type">Integer</span>,
  phone: <span class="hljs-type">Integer</span>,
  email: String
}
</code></pre>
<p>There is no need to overthink this point! More details is another way of saying more information or more complexity.</p>
<p>The only other key point is to understand what a <strong>representation</strong> is.</p>
<h3 id="heading-how-to-represent-something">How to Represent Something</h3>
<p>Suppose you are going to travel somewhere which has a particularly deadly kind of venomous snake. In order to gain information about this snake, you have a few different options:</p>
<ul>
<li><p>Read a verbal description of the snake and its behaviour</p>
</li>
<li><p>Look at a drawing or picture of the snake</p>
</li>
<li><p>Listen to audio of what it sounds like when behaving aggressively</p>
</li>
</ul>
<p>All of the above points are examples of different kinds of representations, or abstractions, of the venomous snake.</p>
<p>In each case, some pieces of information, which accurately represent properties of the real snake, are conveyed. However, neither a verbal description, nor an image, nor a recording can bite you!</p>
<p>Here we see the main utility of abstractions: <strong>Conveying important information</strong> (also known as details or properties) of an object or concept, <strong>while leaving out the unnecessary information</strong>.</p>
<h2 id="heading-how-to-use-abstractions-in-your-programs">How to Use Abstractions In Your Programs</h2>
<p>Before we discuss some specifics, it is worth mentioning that everything in a computer program is technically an abstraction.</p>
<p>In fact, <strong>programming languages, as well as all forms of mathematics, are systems of abstractions</strong>.</p>
<p>However, programmers tend to think of abstractions as a narrow band of software entities usually referred to as:</p>
<ul>
<li><p>Interfaces or Protocols</p>
</li>
<li><p>Abstract Classes</p>
</li>
<li><p>Function Types/References/Signatures</p>
</li>
<li><p>Super/Parent-Classes</p>
</li>
</ul>
<p>Unfortunately, the names and mechanics of the above software entities can vary substantially in different programming languages.</p>
<p>For this reason, I will take two examples which may be more or less appropriate to your preferred languages:</p>
<ol>
<li><p>An interface or protocol (which will also cover abstract classes)</p>
</li>
<li><p>A function type or method reference</p>
</li>
</ol>
<p>In any case, don't worry so much about the names or any minor differences in how these things work across languages. Instead, I invite you to focus on the general ideas.</p>
<h2 id="heading-how-to-use-interfaces-and-protocols">How to Use Interfaces and Protocols</h2>
<p>I will use the term interface from here on, but this term is synonymous with protocol. I will also use the term function synonymously with method.</p>
<p>Interfaces allow you to define behaviour of functions, classes, or objects, without defining their implementation.</p>
<p>Don't worry, I am not like some teachers who throw out some jargon and pretend like I am teaching you something.</p>
<p>Let's look at exactly what I mean by behaviour and implementation.</p>
<p><strong>Behaviour</strong> literally means a function declaration:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserDataSource</span> </span>{
<span class="hljs-comment">//this line below has a function declaration but no function "body"</span>
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getUserById</span><span class="hljs-params">(id: <span class="hljs-type">String</span>)</span></span>: User?
}

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
  <span class="hljs-keyword">val</span> id: String,
  <span class="hljs-keyword">val</span> someData: Any
)
</code></pre>
<p>You can see the footnotes below regarding my usage of the term “function declaration.”</p>
<p>To translate this into English, this function declaration says the we are defining a function which:</p>
<ul>
<li><p>Is named “getUserById”</p>
</li>
<li><p>Accepts a String type called “id” as an argument when called</p>
</li>
<li><p>Returns a “User” or a null value if no user exists (this is because we have a “?” after the “User” type)</p>
</li>
</ul>
<p><strong>Implementation</strong> refers to the function body:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//Note that ":" is short for extends/implements in Kotlin for the class</span>
<span class="hljs-comment">//declaration</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDatabase</span></span>(): UserDataSource {
<span class="hljs-comment">//the curly braces, and everything between them, is the implementation</span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getUserById</span><span class="hljs-params">(id: <span class="hljs-type">String</span>)</span></span>: User? {
    <span class="hljs-keyword">var</span> user: User? = <span class="hljs-literal">null</span>
    <span class="hljs-comment">//… not important for this example</span>
    <span class="hljs-keyword">return</span> user
  }
}
</code></pre>
<p>Another name for the function inside of the interface is an <em>abstract function</em>. Hopefully, our discussion on abstract meaning “<em>less detail</em>” is starting to make more sense here!</p>
<p><strong>Some notes for accuracy:</strong></p>
<ol>
<li><p>Some languages have features to define properties, variables, and even implementations (that is, function declarations + function bodies) within interfaces. This does not change the primary purpose of interfaces, though.</p>
</li>
<li><p>The term function declaration will be defined differently depending on the language. Instead of worrying about verbal definitions, please consider my code examples to follow what I mean.</p>
</li>
</ol>
<h3 id="heading-what-about-abstract-classes">What About Abstract Classes?</h3>
<p>Apart from in Python (and perhaps other languages I am not aware of), abstract classes are very similar to interfaces except for one key difference: a <strong>class may only inherit from a single abstract class.</strong></p>
<p>In my opinion, before languages started to include ways for interfaces to define their own implementations, the use of abstract classes versus interfaces was clear:</p>
<ul>
<li><p>If you only want to share behaviour across a set of software entities, use an interface</p>
</li>
<li><p>If you want to share implementation <strong>and</strong> behaviour, use an abstract class instead</p>
</li>
</ul>
<p>Unfortunately, this distinction is very blurry since many languages now have features to add implementation to interfaces (like Java’s Default Methods).</p>
<p>The only general recommendation I can make which does not account for the specific details of any particular programming language is this: Use the simplest construct to get the job done.</p>
<h2 id="heading-how-to-use-function-types-and-lambda-expressions">How to Use Function Types and Lambda Expressions</h2>
<p>There are different ways to achieve abstraction without defining interfaces or classes. But the amount of structure these language features require is still subject to language specifics.</p>
<p>Kotlin provides enough of these features that you will hopefully be able to make some connections with your preferred languages.</p>
<h3 id="heading-how-to-use-function-types-instead-of-an-interface">How to Use Function Types Instead Of An Interface</h3>
<p>We will start with a practical example and then explain the finer details part by part.</p>
<p>Suppose we want to set up an abstract function (recall that this means a function with no implementation) to handle a click event.</p>
<p>Using something like an interface, we could do the following:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//assume this is an platform/OS component that tells you when</span>
<span class="hljs-comment">//a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: ClickListener? = <span class="hljs-literal">null</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">//Note: the "?" means handleClick() is only</span>
    <span class="hljs-comment">//called when clickListener is NOT NULL</span>
    clickListener?.handleClick()
  }
}
<span class="hljs-comment">//This interfaces hides (abstracts) the concrete class/type</span>
<span class="hljs-comment">//which handles the click</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ClickListener</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span>
}
<span class="hljs-comment">//This concrete class/type handles the click</span>
<span class="hljs-comment">//by extending the interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ScreenController</span></span>() : ClickListener {
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Click handled."</span>)
  }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  PlatformComponent(
    ScreenController()
  ).userClickedScreen()
}
</code></pre>
<p>An alternative approach is to use a function type instead of an interface:</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> controller = ScreenController()
  <span class="hljs-keyword">val</span> component = PlatformComponent(
    <span class="hljs-comment">//The double colon tells the compiler that we are referring to</span>
    <span class="hljs-comment">//the function handleClick defined in ScreenController</span>
    controller::handleClick
  )
  component.userClickedScreen()
}

<span class="hljs-comment">//assume this is an platform/OS component that tells</span>
<span class="hljs-comment">//you when a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">//This is equivalent to calling ScreenController.handleClick(),</span>
    <span class="hljs-comment">//but PlatformComponent does not know that. Abstraction!</span>
    clickListener()
  }
}
<span class="hljs-comment">//This concrete class/type handles the click</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ScreenController</span></span>() {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Click handled."</span>)
  }
}
</code></pre>
<p>In this example, we can see how there is even less structure required to achieve the same result. But keep in mind that having less structure does not immediately imply better code. Really, <strong>it depends</strong>.</p>
<p>In any case, with a practical example in mind, we can break down how this code actually works in more detail.</p>
<h3 id="heading-how-to-use-function-references">How to Use Function References</h3>
<p>If you are unfamiliar with how function types, method references (or whatever else they are called) work, this section explains them in Kotlin. Feel free to jump to the next section if you are already familiar.</p>
<p>Similar to most modern programming languages, we can create a reference variable to a particular function in Kotlin:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
</code></pre>
<p>In Kotlin, function types have the following syntax:</p>
<pre><code class="lang-kotlin">(optional list of parameter types) -&gt; <span class="hljs-keyword">return</span> type
</code></pre>
<p>For example:</p>
<ul>
<li><p><code>(Int, Int) -&gt; Int</code> means that the associated function must take in two Int parameters, and return a single Int</p>
</li>
<li><p><code>() -&gt; Unit</code> means that a function has no parameters and executes without returning a meaningful value</p>
</li>
</ul>
<p>Unit is roughly equivalent to Java’s void return type or Python’s None type – at least in principle.</p>
<p>When it comes time to call (invoke) a function reference, we have two options:</p>
<ul>
<li><p><code>clickListener()</code> for short</p>
</li>
<li><p><code>clickListener.invoke()</code> is the full syntax, which is necessary when making null-safe calls like <code>clickListener?.invoke()</code>, for example</p>
</li>
</ul>
<h3 id="heading-how-to-use-lambda-expressions">How to Use Lambda Expressions</h3>
<p>In the previous example, it is worth noting that ScreenController does not care what the actual function it is invoking happens to be named.</p>
<p>We can take this level of abstraction even further, by not even defining a ScreenController:</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-comment">//note that the outer parenthesis are optional in Kotlin,</span>
  <span class="hljs-comment">//but may make this easier to understand</span>
  <span class="hljs-keyword">val</span> component = PlatformComponent(
    { println(<span class="hljs-string">"Click handled."</span>) }
  )
  component.userClickedScreen()
}
<span class="hljs-comment">//assume this is an platform/OS component that tells</span>
<span class="hljs-comment">//you when a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    clickListener()
  }
}
</code></pre>
<p>Unlike the previous examples, this one is <strong>not intended to resemble a practical scenario</strong> – just to demonstrate a lambda expression.</p>
<p>The actual lambda expression is this:</p>
<p><code>{ println(“Click handled.”) }</code></p>
<p>As you can see, it does not get much more abstract than a lambda expression.</p>
<p>On the surface, it's almost like defining only the implementation but not the behaviour. But at least in Kotlin, the lambda expression must conform to the type we are assigning it to.</p>
<p>In this case, <code>{ println(“Click handled.”) }</code> has no parameters and does not return a meaningful value. So it conforms to <code>() -&gt; Unit</code>.</p>
<h3 id="heading-which-approach-should-i-use">Which Approach Should I Use?</h3>
<p>You may wonder which approach you should be using – assuming your language allows for multiple approaches.</p>
<p>The most accurate answer I can give you is that there is no general rule.</p>
<p>Plenty of teachers these days will say “<em>x</em> is worse than y” or simply “<em>x</em> is bad,” because it works great for clickbait and search engine optimization.</p>
<p>But a language, platform, code construct, architecture, and just about anything else can only be judged good, bad, better, or worse relative to your requirements.</p>
<p>In fact, different requirements are the reason we have languages as different as Python and Java which are both extremely popular.</p>
<p>So instead, try different approaches and be skeptical of anyone who makes absolute statements without discussing requirements.</p>
<h2 id="heading-is-abstraction-the-most-important-idea-in-programming">Is Abstraction the Most Important Idea in Programming?</h2>
<p>The point of this article was never to say: <em>“Using interfaces and abstract classes everywhere will make you a better programmer.”</em></p>
<p>In fairness, as many developers do, I went through a phase around 2016–2018 where I did actually think that statement was pretty accurate.</p>
<p>Instead, the point of this article is to explain two things:</p>
<ul>
<li><p>Abstraction in programming, in my opinion, <strong>should</strong> <strong>not specifically mean abstract classes, or any particular code construct</strong></p>
</li>
<li><p>Abstraction in programming is a <strong>process</strong> by which we design our software entities according to <strong>how much detail</strong> they internally (privately) contain and externally (publicly) provide</p>
</li>
</ul>
<p>In a sense, every decision we make about the structure of our code, regardless of the language, comes down to this process of abstraction.</p>
<p>With that being said, how do we know when making some aspect of our program more abstract is beneficial, useless, or detrimental?</p>
<h2 id="heading-how-much-abstraction-do-i-need">How Much Abstraction Do I Need?</h2>
<p>I can only think of one kind of situation where you should strongly consider using something like an interface or function type.</p>
<p>Recall that these software entities provide variability of implementation but consistent behaviour. Further, that implementation typically refers to the body of a function.</p>
<p>Two things follow from that observation:</p>
<ul>
<li><p>If no variability of implementation is required, there is not likely to be a benefit of using a more abstract software entity.</p>
</li>
<li><p>If variability of implementation is required, using a more abstract software entity is likely beneficial.</p>
</li>
</ul>
<p>We will now discuss two situations I have encountered where variability is a requirement.</p>
<h3 id="heading-how-to-make-your-code-easier-to-test">How to Make Your Code Easier to Test</h3>
<p>Suppose that we have some kind of software entity, which must request some user data from a database or network adapter:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PresentationLogic</span></span>(
 <span class="hljs-keyword">val</span> datasource: Datasource
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">start</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> someData = datasource.getData()
        presentData(someData)
    }

    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Datasource</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data {
        <span class="hljs-keyword">var</span> someData = getLocalOrRemoteData()
        <span class="hljs-comment">//... error handling and so on</span>

        <span class="hljs-keyword">return</span> someData
    }
}
</code></pre>
<p>Also suppose that we want to test <code>PresentationLogic</code> without needing a real datasource to supply the data.</p>
<p>There are a few different ways to solve this problem (see the note below), but a simple solution is to make the datasource more abstract:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PresentationLogic</span></span>(
 <span class="hljs-keyword">val</span> datasource: DatasourceInterface
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">start</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> someData = datasource.getData()
        presentData(someData)
    }

    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DatasourceInterface</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data
}
</code></pre>
<p>From there, we can create a fake implementation of the datasource in a test environment:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeDatasource</span></span>(): DatasourceInterface {
        <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data {
            <span class="hljs-keyword">return</span> Data()
        }
}

<span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">testLogic</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> logic = PresentationLogic(
       <span class="hljs-comment">//here we provide the fake version</span>
       FakeDatasource()
    )
}
</code></pre>
<p>Using abstraction, PresentationLogic does not know or care whether it is talking to a fake or real datasource. By extension, it does not need to change to work with either of them. Variability of implementation!</p>
<p>Note that there are other way to achieve this variability apart from using an interface. You could use a mocking library, or configure a build tool to swap out implementations.</p>
<p>There is no clear answer to which approach is better outside of discussing specific requirements.</p>
<p>Also, note that this approach would not actually work unless the details of how the datasource is created are kept separate from <code>PresentationLogic</code>.</p>
<p>This is commonly referred to as Dependency Injection, which I will discuss in a separate article.</p>
<h3 id="heading-how-to-work-with-different-versions-and-vendors-of-a-service">How to Work With Different Versions and Vendors of a Service</h3>
<p>Suppose that for some reason, you must work with different versions or vendors of the same service depending on different requirements.</p>
<p>An example could be supporting both AWS and Firebase to store the same data. Another example could be supporting a legacy version of a service along with a newer version of that same service.</p>
<p>In any case, it is another situation where variability of implementation is expected.</p>
<p>The code examples we will discuss have the following requirements:</p>
<ul>
<li><p>A client program must use three services, all from different vendors, to perform the same behaviour</p>
</li>
<li><p>The decision to choose a particular service is determined at runtime based on the environment (platform, OS, hardware, and so on) of the client program</p>
</li>
</ul>
<p>For those wondering, “client” in this context is a generic word for some program or software entity which uses other programs or software entities.</p>
<p>For example, YouTube’s website and mobile apps are “client apps” of YouTube’s backend servers.</p>
<p>Without applying any abstraction, our client program will need to know about every possible service and be told which service to choose:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clientProgram</span><span class="hljs-params">(
    request: <span class="hljs-type">Request</span>, 
    awsService: <span class="hljs-type">AwsService</span>,
    firebaseService: <span class="hljs-type">FirebaseService</span>,
    parseService: <span class="hljs-type">ParseService</span>
)</span></span>: Result {
    <span class="hljs-keyword">val</span> use: USE_SERVICE = determineBestService()

    <span class="hljs-keyword">val</span> result = <span class="hljs-keyword">when</span> (use) {
        USE_SERVICE.AWS -&gt; awsService.executeRequest(request)
        USE_SERVICE.FIREBASE -&gt; firebaseService.executeRequest(request)
        USE_SERVICE.PARSE -&gt; parseService.executeRequest(request)
    }

    <span class="hljs-comment">//assume additional work is done before returning the result</span>
    <span class="hljs-keyword">return</span> result
}

<span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">USE_SERVICE</span> </span>{
    AWS,
    FIREBASE,
    PARSE
}
</code></pre>
<p>Notice that clientProgram has a parameter which refers to specific vendors of the service:</p>
<ul>
<li><p>Amazon Web Services (AWS)</p>
</li>
<li><p>Firebase</p>
</li>
<li><p>The now defunct Parse service from Facebook</p>
</li>
</ul>
<p>It follows that any changes to our services will require <code>clientProgram</code> to be refactored (rewritten) appropriately.</p>
<p>The reason I chose Parse as one of the example services is specifically because it was shut down, despite being widely used. There are various reasons why a particular service may no longer fit requirements, but not working any more is a good one.</p>
<p>An alternative approach would be to hide all the details about the service being used from clientProgram. You could use an interface, but for variety’s sake I have used a function type instead:</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-comment">//Creating the services</span>
    <span class="hljs-keyword">val</span> awsService = AwsService()
    <span class="hljs-keyword">val</span> firebaseService = FirebaseService()

    <span class="hljs-comment">//determining which service to use must </span>
    <span class="hljs-comment">//not be included in clientProgram</span>
    <span class="hljs-keyword">val</span> use: USE_SERVICE = determineBestService()

    <span class="hljs-comment">//Assign serviceToUse to the appropriate function</span>
    <span class="hljs-keyword">val</span> serviceToUse: (Request) -&gt; Result = <span class="hljs-keyword">when</span> (use) {
        USE_SERVICE.AWS -&gt; awsService::executeRequest
        USE_SERVICE.FIREBASE -&gt; firebaseService::executeRequest
    }

    <span class="hljs-keyword">val</span> request = getRequest()

    clientProgram(
       request,
       serviceToUse
    )
}


<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clientProgram</span><span class="hljs-params">(
    request: <span class="hljs-type">Request</span>, 
    service: (<span class="hljs-type">Request</span>) -&gt; <span class="hljs-type">Result</span>
)</span></span>: Result {

    <span class="hljs-keyword">val</span> result = service.invoke(request)

    <span class="hljs-comment">//assume additional work is done before returning the result</span>

    <span class="hljs-keyword">return</span> result
}

<span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">USE_SERVICE</span> </span>{
    AWS,
    FIREBASE
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AwsService</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">executeRequest</span><span class="hljs-params">(request: <span class="hljs-type">Request</span>)</span></span>: Result = Result()
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FirebaseService</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">executeRequest</span><span class="hljs-params">(request: <span class="hljs-type">Request</span>)</span></span>: Result = Result()
}
</code></pre>
<p>The end result of this abstraction is that we can change services without needing to change <code>clientProgram</code> – assuming our behaviour does not change.</p>
<p>I want to point out that I am not advocating that you hide every service behind some kind of abstraction. If no variability is required or expected, there may not be any benefit to extra abstraction.</p>
<h1 id="heading-closing-thoughts">Closing Thoughts</h1>
<p>I hope it is clear when reading this article that my intention is not to push dogmatic opinions about how abstract your code should be.</p>
<p>As a junior and intermediate developer, it took me a few years to realize that it really does depend on project requirements.</p>
<p>I also hope that this article gave you some new ideas and perspectives about what abstraction is and how it can be applied in your code. Good luck and happy coding!</p>
<h3 id="heading-before-you-go"><strong>Before you go...</strong></h3>
<p>If you liked this article and want more information on these principles and code constructs, check out my free, full length <a target="_blank" href="https://youtu.be/FL2SMZxNQlc">programming fundamentals course</a>. It includes professionally written English, Burmese, and Arabic subtitles.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Kotlin in 14 Hours ]]>
                </title>
                <description>
                    <![CDATA[ Kotlin is the most popular programming language for building Android apps and it can also be can be used for any kind of development. We just published a full Kotlin course for beginners on the freeCodeCamp.org YouTube channel. Alex Cristian develope... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-kotlin-complete-course/</link>
                <guid isPermaLink="false">66b204a908bc664c3c097ed8</guid>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 27 Oct 2022 14:21:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/kotlin.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Kotlin is the most popular programming language for building Android apps and it can also be can be used for any kind of development.</p>
<p>We just published a full Kotlin course for beginners on the freeCodeCamp.org YouTube channel.</p>
<p>Alex Cristian developed this course. Alex is an experienced developer who has created multiple Android apps.</p>
<p>This course will teach you Kotlin starting from the absolute beginning and going through advanced Kotlin concepts. The course uses intuitive and practical examples and at the end of each section there is a challenge to test your understanding.</p>
<p>Here are the sections covered in this course:</p>
<ul>
<li>Introduction</li>
<li>Install Intellij IDEA</li>
<li>Hello World</li>
<li>Variables</li>
<li>Window</li>
<li>Integer Type</li>
<li>DataType: Byte, Short and Long</li>
<li>Float and Double</li>
<li>Char and Boolean</li>
<li>Operators</li>
<li>Comments</li>
<li>IfThenElse: Statement-Expression</li>
<li>Less Than or Equal To Operator</li>
<li>logical AND operator</li>
<li>logical OR operator</li>
<li>When Statement-Expression</li>
<li>Null</li>
<li>Functions</li>
<li>Function: return and expressions</li>
<li>Functions Overloading</li>
<li>Functions Default Values</li>
<li>Functions vararg keyword</li>
<li>loops: FOR loop</li>
<li>loops: WHILE and DO WHILE loop, Labels and continue and break</li>
<li>loops Challenge</li>
<li>Arrays</li>
<li>Arrays Challenge</li>
<li>OOP: Classes</li>
<li>OOP: Primary Constructor</li>
<li>OOP: Initializer Blocks</li>
<li>OOP: Secondary Constructors</li>
<li>OOP: Constructor Parameters Default Values</li>
<li>OOP: Getters and Setters</li>
<li>OOP: lateinit keyword</li>
<li>OOP: Companion Object</li>
<li>OOP: Singleton</li>
<li>OOP: Lazy Initialization</li>
<li>OOP: Enum Classes</li>
<li>OOP: Inner Classes</li>
<li>OOP Challenge</li>
<li>OOP: Inheritance 1</li>
<li>OOP: Inheritance 2</li>
<li>OOP: Sealed Class</li>
<li>OOP: Abstract Classes</li>
<li>OOP: Data Class</li>
<li>OOP: Interfaces 1</li>
<li>OOP: Interfaces 2</li>
<li>OOP: Object Expression</li>
<li>OOP: Delegation</li>
<li>Lambda Functions and Lambda Expressions</li>
<li>it parameter in lambda</li>
<li>List, Set, Map</li>
<li>Mapping</li>
<li>Zipping</li>
<li>Flatten</li>
<li>String Representation</li>
<li>Filtering</li>
<li>Test predicates: any(), none(), all()  </li>
<li>Plus and Minus Operators</li>
<li>Grouping</li>
<li>Retrieve Collection parts</li>
<li>Retrieve Single Elements</li>
<li>Aggregate Operations: sum(), count(), average(), minOrNull(), maxOrNull()</li>
<li>Comparable and Comparator</li>
<li>Binary Search</li>
<li>Generics: Type Paramenters and Casting</li>
<li>Generics: Upper Bounds</li>
</ul>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/EExSSotojVI">the freeCodeCamp.org YouTube channel</a> (13-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/EExSSotojVI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy a Kotlin Microservice to AWS with App Runner ]]>
                </title>
                <description>
                    <![CDATA[ By Piotr Wolak Hello, everyone. In this step-by-step tutorial, I would like to show you how to deploy a Kotlin Microservice using Docker and AWS App Runner.  Together, we will learn: what exactly is AWS App Runner?  how to configure AWS Command Line... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/kotlin-aws-app-runner/</link>
                <guid isPermaLink="false">66d4608bd1ffc3d3eb89de34</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ktor ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 15 Apr 2022 06:34:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/kotlin-aws-app-runner.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Piotr Wolak</p>
<p>Hello, everyone. In this step-by-step tutorial, I would like to show you how to deploy a Kotlin Microservice using Docker and AWS App Runner. </p>
<p>Together, we will learn:</p>
<ul>
<li>what exactly is AWS App Runner? </li>
<li>how to configure AWS Command Line Interface on your local machine </li>
<li>how to push Docker images to Amazon Elastic Container Registry (ECR)</li>
<li>and finally, how to deploy our containerized application with AWS App Runner</li>
</ul>
<p>I know, it might sound like a tremendous amount of work. But I am convinced that you will find out how simple it can be with the above tech stack.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start, make sure that you have <strong>Docker</strong> already installed on you local machine. We'll need to containerize our application. </p>
<p>If you don't have Docker, then the official <a target="_blank" href="https://docs.docker.com/engine/install/">Docker documentation</a> will help you set it up in a few minutes. </p>
<h2 id="heading-what-exactly-is-aws-app-runner">What Exactly is AWS App Runner?</h2>
<p>First, let's take minute to understand what exactly <strong>AWS App Runner</strong> is.</p>
<p>To put it simply, it is a fully managed service which allows you to build and deploy containerized web applications and APIs with ease. </p>
<p>It takes care of plenty of things, like traffic load balancing, or scaling, which helps developers like you and me focus on the code. </p>
<p><strong>AWS App Runner</strong> oftentimes is a great choice when creating a demo or proof of concept, but it's also worth considering for smaller teams without a dedicated person working on infrastructure. </p>
<h2 id="heading-how-to-create-asimple-kotlin-microservice">How to Create  aSimple Kotlin Microservice</h2>
<p>With that being said, let's prepare a simple REST API using Kotlin and Ktor. </p>
<p>If you are not interested in the Ktor implementation, then you can simply clone <a target="_blank" href="https://github.com/codersee-blog/ktor-app-runner-skeleton">this GitHub repository</a> and proceed to the <em>How to Build the Docker Image</em> step. </p>
<p>If you are using the IntelliJ IDEA Ultimate Edition, then you can create a Ktor project using the app. Otherwise, you can use the <a target="_blank" href="https://start.ktor.io/">Ktor Project Generator</a> tool and download project to your local machine.</p>
<p>Regardless of your choice, make sure to import the following plugins: </p>
<ul>
<li>ContentNegotiation</li>
<li>kotlinx.serialization</li>
<li>Routing</li>
</ul>
<h3 id="heading-how-to-configure-serialization">How to Configure Serialization</h3>
<p>After you've imported the project, create the <code>Serialization.kt</code> file and register <code>application/json</code> content type to the ContentNegotiation feature:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> Application.<span class="hljs-title">configureSerialization</span><span class="hljs-params">()</span></span> {
    install(ContentNegotiation) {
        json()
    }
}
</code></pre>
<p>In simple words, with this code snippet we will be able to serialize Kotlin objects into JSON (and deserialize the JSON into objects, as well). </p>
<h3 id="heading-how-to-create-a-dto">How to Create a DTO</h3>
<p>Now let's implement a <code>MessageDto</code> data class like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Serializable</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MessageDto</span></span>(<span class="hljs-keyword">val</span> message: String)
</code></pre>
<p>Basically, we will use this generic class to provide messages for our API consumers. </p>
<h3 id="heading-how-to-expose-endpoints">How to Expose Endpoints</h3>
<p>As the next step, let's create a <code>Routing.kt</code> file and expose a new endpoint: </p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> Application.<span class="hljs-title">configureRouting</span><span class="hljs-params">()</span></span> {
    routing {
        helloWorldRoute()
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> Routing.<span class="hljs-title">helloWorldRoute</span><span class="hljs-params">()</span></span> {
    route(<span class="hljs-string">"/hello"</span>) {
        <span class="hljs-keyword">get</span> {
            call.respond(HttpStatusCode.OK, MessageDto(<span class="hljs-string">"Hello World!"</span>))
        }
    }
}
</code></pre>
<p>As you can see, our application will respond with a <strong>200 OK</strong> status code to each <code>GET</code> request to the <code>/hello</code> path.</p>
<h3 id="heading-how-to-configure-the-app">How to Configure the App</h3>
<p>Now, let's combine everything inside the <code>Application.kt</code> file: </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> {
    embeddedServer(Netty, port = <span class="hljs-number">8080</span>, host = <span class="hljs-string">"0.0.0.0"</span>) {
        configureRouting()
        configureSerialization()
    }.start(wait = <span class="hljs-literal">true</span>)
}
</code></pre>
<p>As you can see, our Kotlin microservice will be a <strong>Netty embedded server</strong> running on <code>localhost:8080</code>. </p>
<p>I highly encourage you to run the application and verify that everything is working properly:</p>
<pre><code>GET localhost:<span class="hljs-number">8080</span>/hello

<span class="hljs-attr">Status</span>: <span class="hljs-number">200</span> OK
Response Body: 
{
    <span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello World!"</span>
}
</code></pre><h3 id="heading-how-to-implement-the-dockerfile">How to Implement the Dockerfile</h3>
<p>Finally, let's add the <code>Dockerfile</code> to the root directory of our project:</p>
<pre><code>FROM openjdk:<span class="hljs-number">8</span>-jdk
EXPOSE <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span>
RUN mkdir /app
COPY ./build/install/com.codersee.ktor-app-runner/ <span class="hljs-regexp">/app/</span>
WORKDIR /app/bin
CMD [<span class="hljs-string">"./com.codersee.ktor-app-runner"</span>]
</code></pre><p>Make sure that the directory specified for the <code>COPY</code> and <code>CMD</code> commands matches the value of <code>rootProject.name</code> inside the <code>settings.gradle.kts</code> file. If the project's name is <code>xyz</code> , then these commands should reflect that:</p>
<pre><code>...
COPY ./build/install/xyz/ <span class="hljs-regexp">/app/</span>
...
CMD [<span class="hljs-string">"./xyz"</span>]
</code></pre><h2 id="heading-how-to-build-the-docker-image">How to Build the Docker Image</h2>
<p>At this point, we have everything we need to build our <strong>Docker Image</strong>, which we will use later for the <strong>AWS App Runner</strong> deployment.</p>
<h3 id="heading-run-the-gradle-command">Run the Gradle Command</h3>
<p>As the first step, let's run the <code>installDist</code> command with Gradle Wrapper: </p>
<pre><code>./gradlew installDist
</code></pre><p>The above command is responsible for assembling the distribution content and installing it on the current machine. Although it might sound difficult, it will simply create necessary files inside the <code>./build/install/{project-name}/</code> directory. </p>
<h3 id="heading-build-the-docker-image">Build the Docker Image</h3>
<p>As the next step, let's build a Docker Image:</p>
<pre><code> docker build -t ktor-aws-runner .
</code></pre><p>As you can see, we named our desired image <code>ktor-aws-runner</code> with the <code>-t</code> option (a shortcut for <code>--tag</code>).</p>
<h3 id="heading-verify-docker-configuration">Verify Docker Configuration</h3>
<p>Finally, let's run our container to make sure that our Kotlin microservice is working properly:</p>
<pre><code>docker run -p <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span> ktor-aws-runner
</code></pre><p>As a word of explanation, the <code>-p</code> flag (<code>--port</code>)  is responsible for publishing the container's <code>8080</code> port to the host <code>8080</code> port. </p>
<p>With that being done, after a few seconds we should see the following message in logs: </p>
<pre><code>Application started <span class="hljs-keyword">in</span> <span class="hljs-number">0.078</span> seconds
</code></pre><p>Similarly, we can perform a GET request to check if the exposed endpoint is responding correctly.</p>
<h2 id="heading-how-to-create-and-configure-an-aws-user">How to Create and Configure an AWS User</h2>
<p>With all of that being done, we can finally start working with AWS. But before we're able to push our Docker Image, we need to make sure that we have <strong>AWS CLI</strong> installed on our local machine. </p>
<p>We can do that easily with the below command: </p>
<pre><code> aws --version

 # Result:
 aws-cli/<span class="hljs-number">2.5</span><span class="hljs-number">.3</span> Python/<span class="hljs-number">3.9</span><span class="hljs-number">.11</span> Windows/<span class="hljs-number">10</span> exe/AMD64 prompt/off
</code></pre><p>The above result indicates that everything is setup correctly. Nevertheless, if we would like to install or update the CLI, then AWS ships with a really good article on that in their <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html">official documentation</a>. </p>
<p>Additionally, we have to have the access to AWS Cloud from our computer – and that's what we are going to set up in this step.</p>
<p>In order to set up the access, let's sign in to the <strong>AWS Management Console</strong> and navigate to the <strong>Users</strong> feature of the <strong>IAM Console</strong>. We can do that easily with the search bar at the top: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/1-1.png" alt="Image shows search results for users query in AWS Management Console" width="600" height="400" loading="lazy"></p>
<p>On the next page, let's click the <strong>Add users</strong> button: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/2-1.png" alt="Image shows empty list of Users in AWS IAM Console" width="600" height="400" loading="lazy"></p>
<p>Then we'll specify the preferred <strong>User name</strong> along with the <strong>Access key</strong> – <strong>Programmatic access</strong> credential type: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/3-1.png" alt="Image shows user name and AWS access type options for new user" width="600" height="400" loading="lazy"></p>
<p>With these settings, we will be able to access AWS using a combination of access key and secret.</p>
<p>With that being done, let's hit the Next button. On this page, we have to select the group for our user. For the purpose of this tutorial, let's create a new one, using the button visible below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/4-2.png" alt="Image shows permissions and permissions boundary settings for new user" width="600" height="400" loading="lazy"></p>
<p>Nextly, let's specify a <strong>Group name</strong> ( <code>admin-group</code> in my case) in the modal and select the <strong>AdministratorAccess</strong>:</p>
<p>For simplicity, we are going to use the AdministratorAccess. But in real-life scenarios, we should always stick to The Principle of Least Privilege.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/5-2.png" alt="Image shows new group name with seleced policy- AdministratorAccess" width="600" height="400" loading="lazy"></p>
<p>After the group is created, let's hit the Next button once again: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/6-2.png" alt="Image shows existing groups and selected admin-group" width="600" height="400" loading="lazy"></p>
<p>On the next page, we have the option of adding <strong>custom tags</strong> as key-value pairs. </p>
<p>But we won't need them today, so let's simply skip this page: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/7-2.png" alt="Image shows add tags (optional) form" width="600" height="400" loading="lazy"></p>
<p>Finally, we will be redirected to the <strong>Review</strong> page, where we can validate our previous steps:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/8-1.png" alt="Image presents Review new user details" width="600" height="400" loading="lazy"></p>
<p>As you can see, everything looks good, so let's click <strong>Create user</strong>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/9-1.png" alt="Image shows created user " width="600" height="400" loading="lazy"></p>
<p>The user was created successfully, so we can finally import our access and secret keys. </p>
<p>Keep in mind that access and secret keys are highly confidential data and you should never share them with anyone!</p>
<p>Let's click the <strong>Download .csv</strong> button and fetch the file. Personally, I named it <code>some_user_credentials.csv</code> , but feel free to pick whatever name you like (and remember it :) ).</p>
<p>Next, let's navigate to the download directory and run the following command:</p>
<pre><code> aws configure <span class="hljs-keyword">import</span> --csv file:<span class="hljs-comment">//some_user_credentials.csv</span>

 # Result:
 Successfully imported <span class="hljs-number">1</span> profile(s)
</code></pre><p>Given the above message, we can expect that everything was set up correctly. Additionally, we can verify that a new file called <code>credentials</code> has been created (or updated) inside the <code>.aws</code> directory. </p>
<p>If you are using Windows then your path will be  <code>C:\Users\[your_user_name]\.aws</code>:</p>
<pre><code>[some-admin]
aws_access_key_id = [your access key id] 
aws_secret_access_key = [your secret]
</code></pre><h2 id="heading-how-to-push-the-docker-image-to-ecr">How to Push the Docker Image to ECR</h2>
<p>At this point, our CLI is properly prepared, so we can learn how to push our local Docker Image to the <strong>Elastic Container Registry</strong>.</p>
<p>As the first step, let's get back to the <strong>Management Console</strong> and type <strong>container registry</strong> in the search bar: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/10-1.png" alt="Image shows search results for 'container reqistry' query" width="600" height="400" loading="lazy"></p>
<p>Let's click on the <strong>Elastic Container Registry</strong> and on the next page, the <strong>Create repository</strong> button. On the next page, let's select a Private repository and specify a name for it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/11-1.png" alt="Image shows create repository general settings" width="600" height="400" loading="lazy"></p>
<p> For the rest of settings, let's leave the default values, just like below: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/12.png" alt="Image shows Image scan and encryption settings" width="600" height="400" loading="lazy"></p>
<p>Finally, let's hit the <strong>Create repository</strong> button.</p>
<p>After that, we will be redirected to the Private repositories list, which now contains our newly created repository: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/13.png" alt="Image presents private repositories with one item- my-ktor-registry on the list" width="600" height="400" loading="lazy"></p>
<p>Let's copy the URI and specify the following command in the terminal on our local machine: </p>
<pre><code>docker tag ktor-aws-runner:latest [your_registry_uri]:latest

# Example: docker tag ktor-aws-runner:latest <span class="hljs-number">111111111111.</span>dkr.ecr.us-east<span class="hljs-number">-1.</span>amazonaws.com/my-ktor-registry:latest
</code></pre><p>Why do we need that? Well, basically, when working with Docker <strong>we need to tag images with registry host and port</strong> (if necessary) in order to push them to any private repository. </p>
<p>With that being done, let's authenticate to the Amazon ECR registry:</p>
<pre><code>aws ecr get-login-password --profile some-admin --region us-east<span class="hljs-number">-1</span> | docker login --username AWS --password-stdin [your registry URI]

# Result:
Login Succeeded
</code></pre><p>After that, we can run the <code>git push</code> command in order to push the image to ECR: </p>
<pre><code>docker push [your_tagged_image] 

# Example: docker push <span class="hljs-number">111111111111.</span>dkr.ecr.us-east<span class="hljs-number">-1.</span>amazonaws.com/my-ktor-registry:latest
</code></pre><p>Depending on your connection it can take some time, but finally, we should see the update list in our repository: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/14.png" alt="Image shows my-ktor-registry images with one item- latest on the list" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-deploy-the-application-to-aws-app-runner">How to Deploy the Application to AWS App Runner</h2>
<p>Now we have everything we need to share our Kotlin microservice with the world :) </p>
<p>Let's get back to the Management Console and search for app runner: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/15.png" alt="Image presents search results for app runner query" width="600" height="400" loading="lazy"></p>
<p>On the next page, let's hit the <strong>Create service</strong> button.</p>
<p>For the Source configuration, let's choose the <strong>Container registry</strong> along with <strong>Amazon ECR</strong>: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/16.png" alt="Image presents source  and deployment settings for new deployment" width="600" height="400" loading="lazy"></p>
<p>As you might have noticed, AWS App Runner can deploy services directly from a source code repository. If you are interested in such a configuration, just get in touch with me via email (contact[at]codersee[dot]com).</p>
<p>Next, let's click Browse and select <strong>previously created image</strong>: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/17.png" alt="Image presents selected image reposiotory and image tag" width="600" height="400" loading="lazy"></p>
<p>Let's click continue and for the Deployment settings let's choose <strong>Manual</strong> and <strong>Create new service role:</strong> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/18.png" alt="Image shows deployment trigger, ECR Access role and Service role name" width="600" height="400" loading="lazy"></p>
<p>The role name is not important in this tutorial, so we can specify any value. </p>
<p>As the next step, let's click Next and on the next page, let's provide a <strong>Service name</strong> along with <strong>CPU</strong>, <strong>Memory</strong> and <strong>Port</strong> information:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/19.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image presents Service name, cpu, memory, environment variables, port and additional configuration settings</em></p>
<p>As you can see, we have chosen the minimum available combination (and that's what I suggest you do as well).</p>
<p>If we would like to specify some additional environment variables or a custom Start command, then this page allows us to do so. But we won't need any environment variables and we have already added a start command to our Docker Image, so let's leave it as it is.</p>
<p>On the Auto scaling page, select the <strong>Custom configuration</strong>: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/20.png" alt="Image shows auto scaling settings with custom configuration set " width="600" height="400" loading="lazy"></p>
<p>Next, let's create a new configuration called <strong>my-configuration</strong>: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/21.png" alt="Image shows add custom auto scaling configuration modal" width="600" height="400" loading="lazy"></p>
<p>As I have mentioned in the beginning, AWS App Runner takes care of plenty of things out of the box. One of them is auto scaling. Although it is a great feature, we have to limit it to our preferences and always remember that more resources means higher costs. </p>
<p>As you can see above, this example configuration <strong>will not scale our Kotlin Microservice</strong>. However, if we increase the Maximum size, then a new instance will be created each time the number of simultaneous request increases by 10. </p>
<p>Let's add the above config and leave the rest of items with their defaults. After we click Next, we will see the Review page with deployment summary. </p>
<p>On this page, let's click <code>Create and Deploy</code> button, which will start the deployment process: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/22.png" alt="Image presents started AWS App Runner deployment process" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/23.png" alt="Image presents deployment logs event called Create service" width="600" height="400" loading="lazy"></p>
<p>And again, this process can take a few minutes. After it finishes, the status will change from <code>Operation in progress</code> to <code>Running</code> and we will be able to test our Ktor REST API.</p>
<p>Just like previously, let's test the <code>GET /hello</code> endpoint. But this time, as a host name of our microservice, we need to use the value from <code>Default domain</code>:</p>
<pre><code>#Example: 

GET https:<span class="hljs-comment">//aaaaaaaaaa.us-east-1.awsapprunner.com/hello</span>

Status: <span class="hljs-number">200</span> OK
Response Body: 
{
    <span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello World!"</span>
}
</code></pre><h2 id="heading-important-notice">🛑 Important Notice</h2>
<p>Please remember to <strong>delete all the resources we've created today</strong>, so that you won't be charged for them. </p>
<p>It's really easy to forget about all the things we create when learning AWS Cloud and at some point, you may exceed your free quota. Thus, it is a good practice to remove all of that. </p>
<h2 id="heading-summary">Summary</h2>
<p>And that's all for this tutorial on how to deploy Kotlin Microservice to AWS Cloud with AWS App Runner. I really hope that after following along with this guide, you're able to easily deploy your applications to Amazon Cloud. </p>
<p>If you enjoyed this material, then you might want to check my <a target="_blank" href="https://codersee.com/articles/">other articles</a>. On my blog, I cover plenty of topics related to Kotlin, Ktor, and Spring Boot. </p>
<p>If you would like to ask me about anything, please reach out to me at <em>contact[at]codersee[dot]com</em>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Swipe Animations to a CardView in an Android App ]]>
                </title>
                <description>
                    <![CDATA[ By Gourav Khunger If you're building an Android app, you should consider adding animations. They can improve your app's user experience and increase retention.  These days, if you see an app that has no animation, it can feel odd and out-dated. And s... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/add-swipe-animations-to-a-card-view-in-android-app/</link>
                <guid isPermaLink="false">66d45edb052ad259f07e4ad2</guid>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ androiddev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ animation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ animations ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 15 Nov 2021 16:09:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/Swiping-Animation-Android-Views.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Gourav Khunger</p>
<p>If you're building an Android app, you should consider adding animations. They can improve your app's user experience and increase retention. </p>
<p>These days, if you see an app that has no animation, it can feel odd and out-dated. And since interactive experiences are kind of the new norm, you'll want to figure out ways to set your app apart.</p>
<h2 id="heading-what-well-build-here">What We'll Build Here</h2>
<p>Now, it might seem difficult to make your app stand out if you just have something basic like a quote sharing app (which is what we are going to work on here). It can be hard to hook the user and keep them interested.</p>
<p>Of course, you could just add two simple buttons to load the next/previous quote and call it a day. But that's pretty basic and any app could do that! Even if you're just building a simple side-project, there's no trade-off for good UX :)</p>
<p>So what we'll do in this tutorial is drop the buttons, and instead have logic where a user can swipe the card to the left. When they've swiped far enough, the app will load a new card with a new quote.</p>
<p>By the end of this post, you will learn how to make a really smooth animated card which a user can swipe that can perform whatever action you choose. Here's a demo of how it works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/iHxFjvI4x.gif" alt="Animation showing smooth slide to refresh swiping animation on a android cardview." width="600" height="400" loading="lazy"></p>
<p>Amazing, right? Let's get into it!</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>For this tutorial, we will use Kotlin as the programming language for our app – but you can easily translate the code to Java and it would work the same.</p>
<p>For reference, this is the quote card that we wish to enable the swipe feature on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/9CVHyoJfV.png" alt="Android card view with a quote." width="600" height="400" loading="lazy"></p>
<p>It is an androidX <code>CardView</code> with a bunch of <code>TextView</code>s and an <code>ImageView</code>. There's also a <code>ProgressBar</code> that gets shown while loading a new quote.</p>
<p>We won't be making the XML code for the user interface. You can <a target="_blank" href="https://github.com/gouravkhunger/QuotesApp/blob/main/app/src/main/res/layout/fragment_quote.xml">get the layout</a> I used here from the GitHub repository, or build your own.</p>
<p><a target="_blank" href="https://github.com/gouravkhunger/QuotesApp">Here's the complete code</a> for our Quotes app, if you wish to check it out. It uses the MVVM design pattern, but this article doesn't rely on what pattern you use for the business logic of your app, as we'll just be working on the UI part.</p>
<p>Now, we're ready to make that awesome swipe interface!</p>
<h2 id="heading-how-to-handle-swipes-in-our-app">How to Handle Swipes in Our App</h2>
<p>To handle swipes, we first need to set a touch listener on the card. Each time an action is performed on the card, the touch listener is called. Within the listener, we will add the logic to do the math and perform the animations.</p>
<p>Here is the blueprint of the touch listener we will be using:</p>
<pre><code class="lang-kotlin">quoteCard.setOnTouchListener(
    View.OnTouchListener { view, event -&gt;
        <span class="hljs-keyword">when</span> (event.action) {
            MotionEvent.ACTION_MOVE -&gt; {
                <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle ACTION_MOVE</span>
            }
            MotionEvent.ACTION_UP -&gt; {
                <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle ACTION_UP</span>
            }
        }

        <span class="hljs-comment">// required to by-pass lint warning</span>
        view.performClick()
        <span class="hljs-keyword">return</span><span class="hljs-symbol">@OnTouchListener</span> <span class="hljs-literal">true</span>
    }
)
</code></pre>
<p>Here, we are specifically listening for 2 actions on the card – the <code>ACTION_MOVE</code> and the <code>ACTION_UP</code>.</p>
<ul>
<li>The <code>ACTION_MOVE</code> event is called when a user starts swiping the card, that is, moving it.</li>
<li>The <code>ACTION_UP</code> is called when a user lifts their finger from the card, basically, when they release it.</li>
</ul>
<p>There are many other action events that we can override, such as <code>ACTION_DOWN</code> that's called when a person gets hold of the view, but we don't need them for this feature.</p>
<p>The basic setup for the card is done, so let's figure out the swiping logic.</p>
<h3 id="heading-the-math-behind-the-swipe-action">The math behind the swipe action</h3>
<p>First, let's re-think <strong>what we want to achieve</strong>. Implementing functionality is easier when you know exactly what you wish to have. Your code will also make more sense when your requirements are clear.</p>
<p>Here, we have a quote card. We want users to be able to swipe it only to the left, and if the minimum threshold to load a new quote is reached, it should move back to its original position and load a new quote.</p>
<p>Now, to achieve this, let's think of it in terms of the card. Let's define the mean position as the center of the card.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/dEnpWr7e4.png" alt="Mean Position of Quote Card" width="600" height="400" loading="lazy">
<em>Mean Position of the Card</em></p>
<p>We want the card to swipe if and only if the user swipes it to the left of the mean position.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/7epeWn53S.gif" alt="Animation illustrating user swipes to the left of the Quote Card" width="600" height="400" loading="lazy">
<em>Swipe only if moved towards the left of mean position</em></p>
<p>So how can we make this happen? </p>
<p>You guessed it – we will calculate the mean position and on the <code>ACTION_MOVE</code> event, we will check if the user swiped to the left and move the card accordingly.</p>
<h3 id="heading-how-to-implement-the-swipe-logic">How to implement the swipe logic</h3>
<p>To implement the logic, we first need to have the starting position of the card, which is fairly easy to calculate. We will just make sure that it is calculated with respect to the full-screen width, not just the card's width.</p>
<p>Place these lines of code before the <code>when(event.action)</code> statement:</p>
<pre><code class="lang-kotlin">quoteCard.setOnTouchListener(
    View.OnTouchListener { view, event -&gt;

        <span class="hljs-comment">// variables to store current configuration of quote card.</span>
        <span class="hljs-keyword">val</span> displayMetrics = resources.displayMetrics
        <span class="hljs-keyword">val</span> cardWidth = quoteCard.width
        <span class="hljs-keyword">val</span> cardStart = (displayMetrics.widthPixels.toFloat() / <span class="hljs-number">2</span>) - (cardWidth / <span class="hljs-number">2</span>)

        <span class="hljs-keyword">when</span> (event.action) {
            ...
        }
        ...
    }
)
</code></pre>
<p>First we get the <code>displayMetrics</code> from resources, which will give us the width of the screen using <code>displayMetrics.widthPixels.toFloat()</code>.</p>
<p>Then we get the <code>cardWidth</code> using the <code>width</code> property of the <code>quoteCard</code>.</p>
<p>Finally, we calculate the starting position of the card using the formula <code>(width of screen/2) - (cardWidth/2)</code>. Essentially, this gives us the x-coordinate of this position of the card:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/NiH3lsseM.gif" alt="Animation highlighting starting position of Quote Card" width="600" height="400" loading="lazy">
<em>Starting position of card.</em></p>
<p>Now, let's implement the code for the <code>ACTION_MOVE</code> event.</p>
<h3 id="heading-how-to-handle-the-actionmove-event">How to handle the <code>ACTION_MOVE</code> event</h3>
<p>Inside the <code>ACTION_MOVE</code> block, we first initialise the <code>newX</code> variable that holds the new x-coordinate that the card has been swiped to.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> newX = event.rawX
</code></pre>
<p><code>event.rawX</code> gives us the absolute value of the new coordinate with respect to the screen width.</p>
<p><code>newX</code> will contain the x-coordinate where the user's finger is, at any given moment. The value <code>0.0</code> for <code>newX</code> means that the user swiped to the left-most part of the screen. And for my emulator, <code>1080.0</code> represents the right-most edge of the screen.</p>
<p>Since, we want the card to swipe only if <code>newX</code> is less than the mean position of the card, we will place an if-condition here to verify that this is the case.</p>
<p>Think of this with simple values. Let's suppose that the mean position of the card is at x-coordinate <code>540.0</code> (small x-coordinate) and the user swipes to <code>710.0</code> (bigger x-coordinate). But we don't want them to be able to swipe to the right. And if the user swipes to <code>320.0</code> (smaller x-coordinate), then we need to carry out the swipe and move the card to the new position.</p>
<p>Here's the code to implement the above logic:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">if</span> (newX - cardWidth &lt; cardStart) { <span class="hljs-comment">// or newX &lt; cardStart + cardWidth</span>
    quoteCard.animate().x(
        min(cardStart, newX - (cardWidth / <span class="hljs-number">2</span>))
    )
    .setDuration(<span class="hljs-number">0</span>)
    .start()
}
</code></pre>
<p>We subtract <code>cardWidth</code> from <code>newX</code> because <code>newX</code> is an absolute value which is not relative to the card. It has a higher value because <code>cardStart</code> is towards the start of the screen, and <code>newX</code> is initially somewhere in the middle (a user would generally swipe from the middle).</p>
<p>We want to compare the value of <strong>shift</strong> in the x-coordinate and median to the value of <code>cardStart</code>, not the value of <strong><code>newX</code></strong>, so we take this into account by subtracting <code>cardWidth</code>.</p>
<p>Then, we carry out the animation using <code>quoteCard.animate()</code> and we change its x coordinate using the <code>x()</code> function.</p>
<p>Now, why do we do <code>min(cardStart, newX - (cardWidth/2))</code>?</p>
<p>This is very interesting and intuitive to understand. From the beginning, we are emphasizing that the card should move only to the left and not to the right. </p>
<p><code>newX - (cardWidth/2))</code> is nothing but the swiped distance towards the left (so subtraction is involved – for the right side, it should be added).</p>
<p>The <code>min()</code> function here returns the minimum of the two values provided. If the swiped distance is less than the <code>cardStart</code>, it is returned, otherwise <code>cardStart</code> is used. This is the condition we want to meet and <code>min()</code> makes it really easy to handle.</p>
<p><code>setDuration(0)</code> ensures that the animation is carried instantaneously (which keeps swiping from feeling laggy). <code>start()</code> actually starts the animation with the given properties.</p>
<p>This animation will clear any doubt your have on how this works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/other.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Visualisation of the aforementioned concept</em></p>
<p>(I don't have expertise on making animations, this was the best I could come up with.)</p>
<p>Here is the final code for the <code>ACTION_MOVE</code> event:</p>
<pre><code class="lang-kotlin">MotionEvent.ACTION_MOVE -&gt; {
    <span class="hljs-comment">// get the new coordinate of the event on X-axis</span>
    <span class="hljs-keyword">val</span> newX = event.rawX

    <span class="hljs-comment">// carry out swipe only if newX - cardWidth &lt; cardStart, that is</span>
    <span class="hljs-comment">// the card is swiped to the left side, not to the right</span>
    <span class="hljs-keyword">if</span> (newX - cardWidth &lt; cardStart) {
        quoteCard.animate()
            .x(
                min(cardStart, newX - (cardWidth / <span class="hljs-number">2</span>))
            )
        .setDuration(<span class="hljs-number">0</span>)
        .start()
    }
}
</code></pre>
<p>You can also include a <code>TextView</code> to the UI that reflects when the user should release the card. Place this code inside the above <code>if</code> statement too:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">if</span> (quoteCard.x &lt; MIN_SWIPE_DISTANCE) textView.text = getString(R.string.releaseCard)
<span class="hljs-keyword">else</span> textView.text = getString(R.string.infoText)
</code></pre>
<p>where <code>MIN_SWIPE_DISTANCE</code> is <code>-250</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// -250 produces best result, feel free to change to your liking</span>
<span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> MIN_SWIPE_DISTANCE = -<span class="hljs-number">250</span> <span class="hljs-comment">// User should move alteast -250 from mean position to load new quote</span>
</code></pre>
<p>Now, the <code>ACTION_MOVE</code> event is handled properly. Let's write the code to handle the <code>ACTION_UP</code> event, that is, when the card is released.</p>
<h3 id="heading-how-to-handle-the-actionup-event">How to handle the <code>ACTION_UP</code> event</h3>
<p>For the <code>ACTION_UP</code> event, we want the card to come back to its original position, wait for about <code>100</code> milliseconds, then load a new quote.</p>
<p>The logic to animate the card is similar, but this time we will make its animation duration about <code>150</code> millisecond to make it look smooth.</p>
<p>First, create a variable <code>currentX</code> that holds the current value of the x coordinate of the quote card. We'll use this variable later.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> currentX = quoteCard.x
</code></pre>
<p>Then, start the animation on the card. Pass the <code>cardStart</code> variable to the <code>x()</code> function to make it return to its original position and set the duration to <code>150</code>.</p>
<pre><code class="lang-kotlin">quoteCard.animate()
    .x(cardStart)
    .setDuration(<span class="hljs-number">150</span>)
<span class="hljs-comment">// continued below</span>
</code></pre>
<p>This time, we set a listener on the animation. A listener is something that keeps an eye on the animation. By using it, we can perform actions on various animation events such as start, end, resume, and more.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// continuation</span>
.setListener(
    <span class="hljs-keyword">object</span> : AnimatorListenerAdapter() {
        <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onAnimationEnd</span><span class="hljs-params">(animation: <span class="hljs-type">Animator</span>)</span></span> {
            viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
                delay(<span class="hljs-number">100</span>)
                <span class="hljs-comment">// check if the swipe distance was more than</span>
                <span class="hljs-comment">// minimum swipe required to load a new quote</span>
                <span class="hljs-keyword">if</span> (currentX &lt; MIN_SWIPE_DISTANCE) {
                    <span class="hljs-comment">// Add logic to load a new quote if swiped adequately</span>
                    viewModel.getRandomQuote()
                    currentX = <span class="hljs-number">0f</span>
                }
            }
        }
    }
)
.start()
</code></pre>
<p>We set a listener to look for the ending of the animation by overriding the <code>onAnimationEnd()</code> function. </p>
<p>As soon as the animation ends, we launch a coroutine (similar to Threads in Java but much more efficient) with a delay of 100 milliseconds. It then checks if the user had swiped further than the <code>MIN_SWIPE_DISTANCE</code> needed to load a new quote. The variable <code>currentX</code> is used for the comparison here.</p>
<p>If the user actually swipes passing the minimum distance, the coroutine is delayed for <code>100</code> milliseconds. Then the view model loads a new random quote from the API, also resetting the <code>currentX</code> variable to <code>0f</code>.</p>
<p>The final code for the <code>ACTION_UP</code> event looks like this:</p>
<pre><code class="lang-kotlin">MotionEvent.ACTION_UP -&gt; {
    <span class="hljs-keyword">var</span> currentX = quoteCard.x
    quoteCard.animate()
        .x(cardStart)
        .setDuration(<span class="hljs-number">150</span>)
        .setListener(<span class="hljs-keyword">object</span> : AnimatorListenerAdapter() {
            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onAnimationEnd</span><span class="hljs-params">(animation: <span class="hljs-type">Animator</span>)</span></span> {
                viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
                    delay(<span class="hljs-number">100</span>)
                    <span class="hljs-comment">// check if the swipe distance was more than</span>
                    <span class="hljs-comment">// minimum swipe required to load a new quote</span>
                    <span class="hljs-keyword">if</span> (currentX &lt; MIN_SWIPE_DISTANCE) {
                        <span class="hljs-comment">// Add logic to load a new quote if swiped adequately</span>
                        viewModel.getRandomQuote()
                        currentX = <span class="hljs-number">0f</span>
                    }
                }
            }
        })
        .start()
    textView.text = getString(R.string.infoText)
}
</code></pre>
<h2 id="heading-final-code">Final Code</h2>
<p>This is the final code for the complete <code>onTouchListener()</code>:</p>
<pre><code class="lang-kotlin">quoteCard.setOnTouchListener(
    View.OnTouchListener { v, event -&gt;

        <span class="hljs-comment">// variables to store current configuration of quote card.</span>
        <span class="hljs-keyword">val</span> displayMetrics = resources.displayMetrics
        <span class="hljs-keyword">val</span> cardWidth = quoteCard.width
        <span class="hljs-keyword">val</span> cardStart = (displayMetrics.widthPixels.toFloat() / <span class="hljs-number">2</span>) - (cardWidth / <span class="hljs-number">2</span>)

        <span class="hljs-keyword">when</span> (event.action) {
            MotionEvent.ACTION_UP -&gt; {
                <span class="hljs-keyword">var</span> currentX = quoteCard.x
                quoteCard.animate()
                    .x(cardStart)
                    .setDuration(<span class="hljs-number">150</span>)
                    .setListener(
                        <span class="hljs-keyword">object</span> : AnimatorListenerAdapter() {
                            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onAnimationEnd</span><span class="hljs-params">(animation: <span class="hljs-type">Animator</span>)</span></span> {
                                viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
                                    delay(<span class="hljs-number">100</span>)

                                    <span class="hljs-comment">// check if the swipe distance was more than</span>
                                    <span class="hljs-comment">// minimum swipe required to load a new quote</span>
                                    <span class="hljs-keyword">if</span> (currentX &lt; MIN_SWIPE_DISTANCE) {
                                        <span class="hljs-comment">// Add logic to load a new quote if swiped adequately</span>
                                        viewModel.getRandomQuote()
                                        currentX = <span class="hljs-number">0f</span>
                                    }
                                }
                            }
                        }
                    )
                    .start()
                textView.text = getString(R.string.infoText)
            }
            MotionEvent.ACTION_MOVE -&gt; {
                <span class="hljs-comment">// get the new co-ordinate of X-axis</span>
                <span class="hljs-keyword">val</span> newX = event.rawX

                <span class="hljs-comment">// carry out swipe only if newX &lt; cardStart, that is,</span>
                <span class="hljs-comment">// the card is swiped to the left side, not to the right</span>
                <span class="hljs-keyword">if</span> (newX - cardWidth &lt; cardStart) {
                    quoteCard.animate()
                        .x(
                            min(cardStart, newX - (cardWidth / <span class="hljs-number">2</span>))
                        )
                        .setDuration(<span class="hljs-number">0</span>)
                        .start()
                    <span class="hljs-keyword">if</span> (quoteCard.x &lt; MIN_SWIPE_DISTANCE) 
                        textView.text = getString(R.string.releaseCard)
                    <span class="hljs-keyword">else</span> textView.text = getString(R.string.infoText)
                }
            }
        }

        <span class="hljs-comment">// required to by-pass lint warning</span>
        v.performClick()
        <span class="hljs-keyword">return</span><span class="hljs-symbol">@OnTouchListener</span> <span class="hljs-literal">true</span>
    }
}
</code></pre>
<p>Congrats! In this tutorial, we've implemented animation that lets a user swipe a card containing a quote to get a new quote.</p>
<p>Don't forget to download the app and test it out yourself. Stars and contributions on the <a target="_blank" href="https://github.com/gouravkhunger/QuotesApp">GitHub repository</a> are welcomed!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now you have learned how to animate a card and handle animation listeners on it. This helps create better UX that makes your app stand out.</p>
<p>Using the knowledge you gained in this post, you can now create most of the following animations for views in Android:</p>
<ul>
<li><strong>Programmatically create sliding animations for Android views.</strong></li>
</ul>
<p>Just as we did in this tutorial.</p>
<ul>
<li><strong>Left to right animation</strong></li>
</ul>
<p>This is fairly simple, just turn the subtraction in the variables to addition and <code>&lt;</code> signs in the <code>if</code> statements to <code>&gt;</code> signs. With these few tweaks here and there, the right to left animations in card view can be turned into left to right ones!</p>
<ul>
<li><strong>You can also show and hide views using animations.</strong></li>
</ul>
<p>For this, you have to keep track of the start position and end position then animate them with <code>alpha()</code> from <code>0</code> to <code>1</code>. For an example, you can refer to my library <a target="_blank" href="https://github.com/gouravkhunger/AccoLib">Accolib</a> to create animated FAQ accordions.</p>
<ul>
<li><strong>Basic animated layout changes can be achieved with view animations.</strong></li>
</ul>
<p>Thanks a lot for reading so far, I hope this post added some value. Subscribe to my newsletter at <a target="_blank" href="https://genicsblog.com">Genics Blog</a> to stay updated with my future articles!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Style and Theme an App With Jetpack Compose ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will learn how to style and theme an application in Jetpack Compose. Compose is a new UI framework for Android (though Desktop and Web support is being developed), which replaces the old XML-based View system. While still in beta ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-style-and-theme-an-app-with-jetpack-compose/</link>
                <guid isPermaLink="false">66d460cb47a8245f78752abd</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Mon, 22 Mar 2021 13:48:12 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/6054c45f687d62084bf67e41.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will learn how to style and theme an application in Jetpack Compose.</p>
<p>Compose is a new UI framework for Android (though Desktop and Web support is being developed), which replaces the old XML-based View system.</p>
<p>While still in beta release as of writing this article, I do not expect this particular part of the library to change drastically for the stable release.</p>
<p>Topics include:</p>
<ul>
<li><p>A brief recap of the XML approach</p>
</li>
<li><p>How to migrate from the XML-based colors, themes, and typography (font) system</p>
</li>
<li><p>How to set up light and dark themes for your apps in only a few lines of code</p>
</li>
<li><p>How to use your new Kotlin-based style information in your composables</p>
</li>
<li><p>How to style Text Composables specifically</p>
</li>
</ul>
<p>Before proceeding, it is important that you understand what a composable is. I will not be stopping to explain that concept here, as I already have in <a target="_blank" href="https://www.freecodecamp.org/news/jetpack-compose-beginner-tutorial-composables-recomposition/">this article</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/81r-vwPxlaw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-we-used-to-style-android-apps-using-xml-resources">How We Used to Style Android Apps Using XML Resources</h2>
<p>As usual, I like to share with you the motivations behind, and a bit of history on, these topics. In case you do not care, feel free to skip to the next section where we get into the practical stuff.</p>
<h3 id="heading-android-resources">Android Resources</h3>
<p>The Android app resources system is something which the Android team deserves a high five for, at least in my opinion. But like every design decision, a feature in one situation becomes a flaw in another situation.</p>
<p>To be specific, one of the greatest challenges for both platform and application developers alike is to create what I will call <strong>localized resources</strong>. I am referring to the challenge of building apps which:</p>
<ul>
<li><p>Display text and graphics in a variety of different languages and alphabets</p>
</li>
<li><p>Look and feel proportionate to a wide variety of form factors (dimensions, densities, and so on.)</p>
</li>
</ul>
<p>Those are just two common examples – there are plenty more. The resource system gives us a place where app developers can provide localized resources which the platform can select for at compile time. This saves us having to write that boilerplate code ourselves.</p>
<h3 id="heading-feature-or-flaw">Feature or Flaw?</h3>
<p>While I would never want to manage the boilerplate code necessary for localized string resources myself, that does not mean I enjoy writing XML.</p>
<p>In fact, <strong>there are very few things I would prefer to do in XML</strong> over a modern, idiomatic, and elegant language such as Kotlin or Swift. Personal preference aside, there is a more technical reason why XML resources are not always ideal.</p>
<p>Please note that this is not meant as a criticism of the platform developers/engineers. It is merely an observation of how design decisions always have benefits and costs.</p>
<p>In order to integrate our XML-based resources into our JVM-based application code, we must necessarily have <strong>layers of translation</strong> (compilation) and <strong>platform bridges</strong> (APIs). This can present difficulties for both platform and application developers.</p>
<p>Two common problems I ran into were:</p>
<ul>
<li><p>I want access to a resource in a place where I do not want tight coupling to the platform APIs which provide the resource</p>
</li>
<li><p>I have to write some ridiculous boilerplate code just to change the look of a View (that is, override something defined within resource styles and themes)</p>
</li>
</ul>
<p>The <strong>root problem</strong> for everyone involved is <strong>tight coupling</strong> to the View system and the Android resource system (which are themselves tightly coupled together).</p>
<p>For the platform developers, this means they have to build on top of, or work around gigantic and old codebases. Add that they must also try to have new features work on older Android OS versions, and that becomes a very thankless job.</p>
<p>The result for us application developers is most often a lot of <strong>boilerplate code,</strong> some <strong>hacky workarounds</strong> for things which intuitively seem like they should be one-liners. Not to mention the main API for getting these resources is <code>Context</code>, which is a class you really do not want to leak in memory.</p>
<p><strong>Enter Jetpack Compose.</strong></p>
<h2 id="heading-how-to-set-up-themes-colors-and-fonts-with-jetpack-compose">How to Set Up Themes, Colors, and Fonts with Jetpack Compose</h2>
<p>With our review of the old system out of the way, let's explore a much prettier and simpler way to style and theme an Android application. I said I would keep this practical, but allow one point.</p>
<p>Since we will be doing that work in Kotlin, it means one very important thing: Both we and the platform developers are much less bound by translation (compilation) and API bridges (Android's <code>R</code> class and <code>Context</code>) between XML and the JVM.</p>
<p>In simple terms, this means <strong>much less boilerplate code</strong>, and <strong>much more control at runtime</strong>.</p>
<p>For the practical part of this article, my suggestion to you is to follow this process in the order I explain it. I have structured it in the order I follow when writing this code in a new App.</p>
<h3 id="heading-how-to-replace-colorsxml-resources-with-kotlin-compose">How to Replace Colors.xml Resources with Kotlin Compose</h3>
<p>If you have not already decided upon a color scheme for your application, I suggest that you use the various resources available on the official Material Design website. Try out:</p>
<ul>
<li><p>The <a target="_blank" href="https://material.io/design/color/the-color-system.html#tools-for-picking-colors">color palettes</a></p>
</li>
<li><p>The <a target="_blank" href="https://material.io/resources/color/">color tool</a></p>
</li>
</ul>
<p>If you plan to support light and dark app themes (explained shortly), try to select a color scheme which supports white text and a color scheme which supports black text.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/color_text_palettes.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Example of light and dark color schemes.</em></p>
<p>Create a file called something like <a target="_blank" href="https://github.com/BracketCove/GraphSudokuOpen/blob/master/app/src/main/java/com/bracketcove/graphsudoku/ui/Color.kt">Color.kt</a> (the name does not matter) and fill it with immutable <strong>val</strong>ues:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> androidx.compose.ui.graphics.Color

<span class="hljs-keyword">val</span> primaryGreen = Color(<span class="hljs-number">0XFF00bc00</span>)
<span class="hljs-keyword">val</span> primaryCharcoal = Color(<span class="hljs-number">0xFF2b2b2b</span>)
<span class="hljs-keyword">val</span> accentAmber = Color(<span class="hljs-number">0xFFffe400</span>)

<span class="hljs-keyword">val</span> textColorLight = Color(<span class="hljs-number">0xDCFFFFFF</span>)
<span class="hljs-keyword">val</span> textColorDark = Color(<span class="hljs-number">0xFFf3f3f3</span>)
<span class="hljs-keyword">val</span> gridLineColorLight = Color.Black
<span class="hljs-comment">//...</span>
</code></pre>
<p>You can either use a predefined value like <code>Color.Black</code> or supply your own ARGB Hex value.</p>
<p>Since ARGB Hex is just a bunch of jargon to describe what the heck "<code>0XFF00bc00</code>" means, let me translate:</p>
<ul>
<li><p>First two characters <code>0x</code> tell the compiler that this is a hexadecimal number</p>
</li>
<li><p>Second two characters , "<code>FF</code>" or "<code>DC</code>", represent Transparency/Opaqueness/<strong>A</strong>lpha in Hex</p>
</li>
<li><p>The remaining six character pairs represent <strong>R</strong>ed, <strong>G</strong>reen, and <strong>B</strong>lue</p>
</li>
</ul>
<h3 id="heading-how-to-add-fonts-and-replace-the-fontfamily-attribute">How to Add Fonts and Replace the <code>fontFamily</code> Attribute</h3>
<p>Typography (fonts) is also very easy to manage. This is the kind of thing where Kotlin's <a target="_blank" href="https://kotlinlang.org/docs/functions.html#default-arguments">default arguments</a> are very useful.</p>
<p>Create a file called something like <a target="_blank" href="https://github.com/BracketCove/GraphSudokuOpen/blob/master/app/src/main/java/com/bracketcove/graphsudoku/ui/Type.kt">Type.kt</a> (the name still does not matter) and create <code>Typography</code> class...:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> typography = Typography(
    body1 = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = <span class="hljs-number">16</span>.sp
    ),

    button = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Bold,
        fontSize = <span class="hljs-number">32</span>.sp
    ),

    caption = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = <span class="hljs-number">12</span>.sp
    )
)
<span class="hljs-comment">//...</span>
</code></pre>
<p>...and some <code>TextStyle</code> classes:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//...</span>
<span class="hljs-keyword">val</span> mainTitle = TextStyle(
    fontFamily = FontFamily.Default,
    fontWeight = FontWeight.Light,
    fontSize = <span class="hljs-number">48</span>.sp,
    textAlign = TextAlign.Center
)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">dropdownText</span><span class="hljs-params">(color: <span class="hljs-type">Color</span>)</span></span> = TextStyle(
    fontFamily = FontFamily.Default,
    fontWeight = FontWeight.Normal,
    fontSize = <span class="hljs-number">32</span>.sp,
    textAlign = TextAlign.Center,
    color = color
)
<span class="hljs-comment">//...</span>
</code></pre>
<p>Whether you provide public functions or values (I advise against using <code>**var**</code> here) is up to your individual preference and current requirements.</p>
<h3 id="heading-how-to-create-an-app-theme-in-jetpack-compose">How to Create an App Theme in Jetpack Compose</h3>
<p>The last thing you need to configure before using your theme in your composables is a <code>MaterialTheme @Composable</code>. I have mine, and along with my light and dark color palettes in a file called <a target="_blank" href="https://github.com/BracketCove/GraphSudokuOpen/blob/master/app/src/main/java/com/bracketcove/graphsudoku/ui/GraphSudokuTheme.kt">GraphSudokuTheme</a>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> androidx.compose.foundation.isSystemInDarkTheme
<span class="hljs-keyword">import</span> androidx.compose.material.MaterialTheme
<span class="hljs-keyword">import</span> androidx.compose.material.darkColors
<span class="hljs-keyword">import</span> androidx.compose.material.lightColors
<span class="hljs-keyword">import</span> androidx.compose.runtime.Composable
<span class="hljs-keyword">import</span> androidx.compose.ui.graphics.Color

<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> LightColorPalette = lightColors(
    primary = primaryGreen,
    secondary = textColorLight,
    surface = lightGrey,
    primaryVariant = gridLineColorLight,
    onPrimary = accentAmber,
    onSurface = accentAmber
)

<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> DarkColorPalette = darkColors(
    <span class="hljs-comment">//main background color</span>
    primary = primaryCharcoal,
    <span class="hljs-comment">//used for text color</span>
    secondary = textColorDark,
    <span class="hljs-comment">//background of sudoku board</span>
    surface = lightGreyAlpha,
    <span class="hljs-comment">//grid lines of sudoku board</span>
    primaryVariant = gridLineColorLight,
    onPrimary = accentAmber,

    onSurface = accentAmber

)

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">GraphSudokuTheme</span><span class="hljs-params">(
    darkTheme: <span class="hljs-type">Boolean</span> = isSystemInDarkTheme()</span></span>,
    content: <span class="hljs-meta">@Composable</span> () -&gt; <span class="hljs-built_in">Unit</span>
) {

    MaterialTheme(
        colors = <span class="hljs-keyword">if</span> (darkTheme) DarkColorPalette <span class="hljs-keyword">else</span> LightColorPalette,
        typography = typography,
        shapes = shapes,
        content = content
    )
}
</code></pre>
<p>Since you should already be familiar with what a composable is (I gave you fair warning), the only new thing here is <code>darkTheme: Boolean = isSystemInDarkTheme()</code>.</p>
<p>To give a simplified explanation, <code>isSystemInDarkTheme()</code> is a call which asks any compatible Android device for the user's preference of a light or dark theme.</p>
<p>It <strong>returns a boolean value</strong> which we can use in a Ternary (Conditional) Assignment expression such as <code>colors = if (darkTheme) DarkColorPalette else LightColorPalette</code>.</p>
<p>That is actually it. Colors, Fonts, and two Themes defined in a few minutes.</p>
<h2 id="heading-how-to-use-a-theme-in-compose">How to Use a Theme in Compose</h2>
<p>It is now time to use this Theme in your app. In this app, which only has two primary screens, I just use an <a target="_blank" href="https://github.com/BracketCove/GraphSudokuOpen/blob/master/app/src/main/java/com/bracketcove/graphsudoku/ui/activegame/ActiveGameActivity.kt">Activity</a> as a <strong>container</strong> for my composables:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">class</span> NewGameActivity : AppCompatActivity(), NewGameContainer {
    //...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //...

        setContent {
            GraphSudokuTheme {
                NewGameScreen(
                    onEventHandler = logic::onEvent,
                    viewModel
                )
            }
        }
        //...
    }
</code></pre>
<p>Wherever you find yourself calling <code>setContent {}</code>, my suggestion for beginners is to immediately place your Theme composable inside of it. Doing so will cause the style information to <strong>cascade/inherit to each nested composable</strong>.</p>
<p>You are done! Almost.</p>
<h2 id="heading-how-to-override-styles-and-themes">How to Override Styles and Themes</h2>
<p>If you can help it, try to include any colors you will want in your light and dark palettes. This way, when you call <code>MaterialTheme.colors.&lt;Color&gt;</code>, the system will handle the conditional logic necessary to pick the appropriate palette:</p>
<pre><code class="lang-pgsql">@Composable
fun NewGameContent(
    onEventHandler: (NewGameEvent) -&gt; Unit,
    viewModel: NewGameViewModel
) {
    Surface(
        Modifier
            .wrapContentHeight()
            .fillMaxWidth()
    ) {
        ConstraintLayout(Modifier.background(MaterialTheme.colors.<span class="hljs-keyword">primary</span>)) { 
            //...
        }
        //...
      }
}
</code></pre>
<p>However, sometimes it is more suitable to write your own conditional logic...or I just got lazy. Fortunately Compose makes many such configurations available as properties:</p>
<pre><code class="lang-pgsql">@Composable
fun DoneIcon(onEventHandler: (NewGameEvent) -&gt; Unit) {
    Icon(
        imageVector = Icons.Filled.Done,
        tint = <span class="hljs-keyword">if</span> (MaterialTheme.colors.isLight) textColorLight 
        <span class="hljs-keyword">else</span> textColorDark,
        contentDescription = <span class="hljs-keyword">null</span>,
        modifier = Modifier
            .clickable(
            //...
            )
    )
}
</code></pre>
<p><code>MaterialTheme.Colors.isLight</code> returns a boolean indicating what mode they are in, then we can use another Ternary Assignment from there.</p>
<h3 id="heading-how-to-style-a-text-composable">How to Style a Text Composable</h3>
<p>Just set the <code>style</code> argument equal to one of your text styles (whether it comes from <code>MaterialTheme</code> or one of the styles within <code>Type.kt</code>):</p>
<pre><code class="lang-kotlin">Text(
    text = stat.toTime(),
    style = statsLabel.copy(
        color = <span class="hljs-keyword">if</span> (isZero) Color.White
        <span class="hljs-keyword">else</span> MaterialTheme.colors.onPrimary,
    fontWeight = FontWeight.Normal
    ),
    modifier = Modifier
        .wrapContentSize()
        .padding(end = <span class="hljs-number">2</span>.dp, bottom = <span class="hljs-number">4</span>.dp),
        textAlign = TextAlign.End
)
</code></pre>
<p><code>TextStyle</code> has its own <code>copy</code> function ready to go should you need to overwrite anything.</p>
<p>And that's it! You now know how to style and theme an application using Jetpack Compose. Thanks for reading :)</p>
<h3 id="heading-social"><strong>Social</strong></h3>
<p>You can find me on <a target="_blank" href="https://www.instagram.com/rkay301/">Instagram here</a> and on <a target="_blank" href="https://twitter.com/wiseAss301">Twitter here</a>.</p>
<h3 id="heading-here-are-some-of-my-tutorials-amp-courses"><strong>Here are some of my tutorials &amp; courses</strong></h3>
<p><a target="_blank" href="https://www.youtube.com/channel/UCSwuCetC3YlO1Y7bqVW5GHg">https://youtube.com/wiseass</a> <a target="_blank" href="https://www.freecodecamp.org/news/author/ryan-michael-kay/">https://www.freecodecamp.org/news/author/ryan-michael-kay/</a> <a target="_blank" href="https://skl.sh/35IdKsj">https://skl.sh/35IdKsj</a> (introduction to Android with Android Studio)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Handle UI Events in Jetpack Compose ]]>
                </title>
                <description>
                    <![CDATA[ In this short and practical article, we will talk about how to handle UI events in Jetpack Compose. In the old system, we used OnClickListeners and other interfaces. In Compose, we can take full advantage of Kotlin’s Sealed Classes, Function Types an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-handle-ui-events-in-jetpack-compose/</link>
                <guid isPermaLink="false">66d460c99f2bec37e2da066a</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android Studio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jetpack Compose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Tue, 16 Mar 2021 18:22:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/03/cat-4793068_1280-5.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this short and practical article, we will talk about how to handle UI events in Jetpack Compose.</p>
<p>In the old system, we used OnClickListeners and other interfaces. In Compose, we can take full advantage of Kotlin’s <strong>Sealed Classes</strong>, <strong>Function Types</strong> and <strong>Lambda Expressions</strong>.</p>
<p>If you do not know what a composable is, consider reading <a target="_blank" href="https://www.freecodecamp.org/news/jetpack-compose-beginner-tutorial-composables-recomposition/">this article which explains the fundamentals</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/LrNPw1LQHEw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-model-ui-events-with-a-sealed-class">How to Model UI Events with a Sealed Class</h2>
<p>First, we must learn what is meant by UI Events and how to model them with Sealed Classes.</p>
<p>I have described this same process for <a target="_blank" href="https://medium.com/swlh/simplify-your-ui-interactions-with-events-java-kotlin-any-language-5062c1b1e0e4">Java and Kotlin</a> (with the old view system) before, so I will keep this brief.</p>
<h3 id="heading-the-process">The Process</h3>
<p>For each screen or sub-screen of your UI, ask yourself this question: What are all the different ways which the user can interact with it?</p>
<p>Let's take an example from my first app built fully in compose, <a target="_blank" href="https://play.google.com/store/apps/details?id=com.bracketcove.graphsudoku">Graph Sudoku</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/graph_sudoku_small_screen.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Screenshot of a Sudoku Android App</em></p>
<p>The sealed class I use to represent the UI interactions of this screen looks like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">sealed</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameEvent</span> </span>{
    <span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OnInput</span></span>(<span class="hljs-keyword">val</span> input: <span class="hljs-built_in">Int</span>) : ActiveGameEvent()
    <span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OnTileFocused</span></span>(<span class="hljs-keyword">val</span> x: <span class="hljs-built_in">Int</span>, 
    <span class="hljs-keyword">val</span> y: <span class="hljs-built_in">Int</span>) : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnNewGameClicked : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnStart : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnStop : ActiveGameEvent()
}
</code></pre>
<p>To explain briefly:</p>
<ul>
<li><p>OnInput represents a user touching an input button (like 0, 1, 2, 3, 4)</p>
</li>
<li><p>OnTileFocused represents a user selecting a tile (like the amber highlighted one)</p>
</li>
<li><p>OnNewGameClicked is self-explanatory</p>
</li>
<li><p>OnStart and OnStop are lifecycle events which my composables do not care about, but they are used in the Activity which acts as a Container for the composables</p>
</li>
</ul>
<p>Once you have your sealed class set up, you can now handle a wide variety of events using a single event handler function. Sometimes it might make more sense to have multiple event handler functions, so keep in mind that <strong>this approach must be adapted to your project's specific requirements</strong>.</p>
<h2 id="heading-how-to-connect-your-software-architecture">How to Connect Your Software Architecture</h2>
<p>What you have handling these events is totally up to you. Some people think that MVVM is the golden standard of software architectures, but it seems like more and more people are realizing that <strong>there is no single architecture which works best for every situation</strong>.</p>
<p>For Android with Compose, my current approach is to use a very 3rd party minimalist approach which typically has these things in each feature (screen):</p>
<ul>
<li><p>A (Presentation) Logic class <strong>as an event handler</strong></p>
</li>
<li><p>A ViewModel to store the data necessary to render the View (as the name implies)</p>
</li>
<li><p>An Activity which acts as a Container (not a god object)</p>
</li>
<li><p>Composables to form the View</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/model_view_whatever-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Model-View-Whatever</em></p>
<p>I do not care what you use as long as you are applying <a target="_blank" href="https://youtu.be/B_C41SF0KbI">separation of concerns</a>. This is how I arrived at this architecture, by simply asking what should and should not be put together in the same class.</p>
<p>Whether you want your ViewModel, a Fragment, or an Activity to be your event handler, all of them can be set up the same way: <strong>Function Types!</strong></p>
<p>Within your class of choice, set up an event handler function which accepts your sealed class as its argument:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameLogic</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> container: ActiveGameContainer?,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> viewModel: ActiveGameViewModel,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> gameRepo: IGameRepository,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> statsRepo: IStatisticsRepository,
    dispatcher: DispatcherProvider
) : BaseLogic&lt;ActiveGameEvent&gt;(dispatcher),
    CoroutineScope {
    <span class="hljs-comment">//...</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onEvent</span><span class="hljs-params">(event: <span class="hljs-type">ActiveGameEvent</span>)</span></span> {
        <span class="hljs-keyword">when</span> (event) {
            <span class="hljs-keyword">is</span> ActiveGameEvent.OnInput -&gt; onInput(
                event.input,
                viewModel.timerState
            )
            ActiveGameEvent.OnNewGameClicked -&gt; onNewGameClicked()
            ActiveGameEvent.OnStart -&gt; onStart()
            ActiveGameEvent.OnStop -&gt; onStop()
            <span class="hljs-keyword">is</span> ActiveGameEvent.OnTileFocused -&gt; onTileFocused(event.x, event.y)
        }
    }
    <span class="hljs-comment">//...</span>
}
</code></pre>
<p>This approach is very organized and makes it easy to test every Unit in this 3rd party library free class through a single entry point.</p>
<p>However, we are not done yet. Naturally, we need a way to get a reference to this event handler function, <code>onEvent</code>, to our Composables. We can do this using a <strong>function reference</strong>:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>(), ActiveGameContainer {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> logic: ActiveGameLogic

    <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-keyword">val</span> viewModel = ActiveGameViewModel()

        setContent {
            ActiveGameScreen(
                onEventHandler = logic::onEvent,
                viewModel
            )
        }

        logic = buildActiveGameLogic(<span class="hljs-keyword">this</span>, viewModel, applicationContext)
    }

      <span class="hljs-comment">//...</span>
}
</code></pre>
<p>I am sure some of you are wondering why I am using an Activity. You can ask me during a <a target="_blank" href="https://youtu.be/-xV8k-4UW50">livestream Q&amp;A sometime for a detailed answer</a>.</p>
<p>In short, Fragments appear to be a bit pointless with Compose with my approach to architecture (I do not use Jetpack Navigation), and there is nothing wrong with using Activities as a feature specific container. <strong>Just avoid writing god activities, basically.</strong></p>
<p>To be specific, the way you make a reference to a function in Kotlin, is by providing the <strong>class/interface name</strong> (or <strong>skip that if it is a Top-Level function</strong>), followed by <strong>two colons</strong>, and the <strong>name of the function without any arguments or brackets</strong>:</p>
<pre><code class="lang-pgsql">onEventHandler = logic::onEvent
</code></pre>
<h2 id="heading-how-to-replace-onclicklistener-with-jetpack-compose-onclick-modifier">How to Replace onClickListener With Jetpack Compose onClick Modifier</h2>
<p>With that stuff ready, we can look at how this works within the composable. Naturally, your root composable will need the event handler function as a parameter:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">ActiveGameScreen</span><span class="hljs-params">(
    onEventHandler: (<span class="hljs-type">ActiveGameEvent</span>) -&gt; <span class="hljs-type">Unit</span>,
    viewModel: <span class="hljs-type">ActiveGameViewModel</span>
)</span></span> {
<span class="hljs-comment">//...</span>
}
</code></pre>
<p>It can be a bit tricky to get function type syntax correctly, but understand that this <strong>really is a reference to a function,</strong> which is not so different from a reference to a class.</p>
<p>Just as you should not build god objects, you should not build giant composables:</p>
<ol>
<li><p>Break your UI down into the <strong>smallest reasonable parts</strong></p>
</li>
<li><p>Wrap them in a composable function</p>
</li>
<li><p>For each composable which has a UI interaction associated with it, <strong>it must be given a reference to your event handler function</strong></p>
</li>
</ol>
<p>Here is a composable which represents the input buttons of the Sudoku app, which is given the event handler by reference:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">SudokuInputButton</span><span class="hljs-params">(
    onEventHandler: (<span class="hljs-type">ActiveGameEvent</span>) -&gt; <span class="hljs-type">Unit</span>,
    number: <span class="hljs-type">Int</span>
)</span></span> {
    Button(
        onClick = { onEventHandler.invoke(ActiveGameEvent.OnInput(number)) },
        modifier = Modifier
            .requiredSize(<span class="hljs-number">56</span>.dp)
            .padding(<span class="hljs-number">2</span>.dp)
    ) {
        Text(
            text = number.toString(),
            style = inputButton.copy(color = MaterialTheme.colors.onPrimary),
            modifier = Modifier.fillMaxSize()
        )
    }
}
</code></pre>
<p>To actually pass the event to the logic class, we must use the <code>invoke</code> function, which will accept arguments as per the function type definition (which accepts an <code>ActiveGameEvent</code> in this case).</p>
<p>At this point, you are ready to handle UI interaction events in Kotlin (compose or not) by taking full advantage of this beautiful and modern programming language.</p>
<p>If you liked this article, share it on social media and consider checking out the resources below to support an independent programmer and content creator.</p>
<h3 id="heading-social">Social</h3>
<p>You can find me on <a target="_blank" href="https://www.instagram.com/rkay301/">Instagram here</a> and on <a target="_blank" href="https://twitter.com/wiseAss301">Twitter here</a>.</p>
<h3 id="heading-here-are-some-of-my-tutorials-amp-courses">Here are some of my tutorials &amp; courses</h3>
<p><a target="_blank" href="https://www.youtube.com/channel/UCSwuCetC3YlO1Y7bqVW5GHg">https://youtube.com/wiseass</a> <a target="_blank" href="https://www.freecodecamp.org/news/author/ryan-michael-kay/">https://www.freecodecamp.org/news/author/ryan-michael-kay/</a> <a target="_blank" href="https://skl.sh/35IdKsj">https://skl.sh/35IdKsj</a> (introduction to Android with Android Studio)</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
