<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tiago Loureiro</title>
    <description>The latest articles on DEV Community by Tiago Loureiro (@tgloureiro).</description>
    <link>https://dev.to/tgloureiro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F185915%2F2bf83176-657b-45ee-835e-3d84fa9b8060.jpeg</url>
      <title>DEV Community: Tiago Loureiro</title>
      <link>https://dev.to/tgloureiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tgloureiro"/>
    <language>en</language>
    <item>
      <title>Meet the Jetpack Splashscreen API: a definitive guide for splash screens in Android</title>
      <dc:creator>Tiago Loureiro</dc:creator>
      <pubDate>Sat, 10 Jul 2021 22:09:07 +0000</pubDate>
      <link>https://dev.to/tgloureiro/the-definitive-guide-for-splash-screens-in-android-58e1</link>
      <guid>https://dev.to/tgloureiro/the-definitive-guide-for-splash-screens-in-android-58e1</guid>
      <description>&lt;p&gt;Splash screens, also called launch screens, are the screens shown by the app as it loads, during the app's startup. They exist to provide a momentary brand exposure or improve the user experience by showing a preview of the app as it starts, which can reduce the user's perceived load time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fmd_splash_screens.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fmd_splash_screens.png" alt="Branded splash example in Material Design docs" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Branded and preview splash screens as in &lt;a href="https://material.io/design/communication/launch-screen.html" rel="noopener noreferrer"&gt;Material Design docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On many projects I've worked on, in addition to showing the splash screen, we had to animate the transition between splash and first app screen. Depending on the animation type and how we're showing the first app views, we can have jank or a perceivable delay between the animations. So, we have to choose the right approach accordingly to the use case.&lt;/p&gt;

&lt;p&gt;In this article you'll see how animated splash screens are created in Android and how this should be done now that we have &lt;a href="https://developer.android.com/jetpack/androidx/releases/core#core-splashscreen-1.0.0-alpha01" rel="noopener noreferrer"&gt;Jetpack's Core SplashScreen&lt;/a&gt;, which backports Android 12 SplashScreen API back to Android Marshmallow (API 23).&lt;/p&gt;

&lt;p&gt;Suppose we have to implement the following branded splash screen for an Android app:&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.figma.com/embed?embed_host=share&amp;amp;url=https%3A%2F%2Fwww.figma.com%2Fproto%2FhVnnsppnHVKxLw68gkyu48%2FSplashScreen-example%3Fnode-id%3D1%253A57%26scaling%3Dscale-down-width%26page-id%3D0%253A1" rel="noopener noreferrer"&gt;Click to see the design on Figma&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that we start with a brand image, fade it out and then begin a slide down transition in the start screen. This use case will let us exercise multiple techniques in splash screen display, despite having simple transitions in the design. The animations must run sequentially and a long delay or jank between them is not acceptable.&lt;/p&gt;
&lt;h1&gt;
  
  
  Simple things first
&lt;/h1&gt;

&lt;p&gt;Let's start simple: showing what happens in Android when you don't set up a splash screen. After creating an &lt;code&gt;'Empty Activity Project'&lt;/code&gt; in Android Studio, the main activity layout was adjusted to have the same design as the start screen reference. Nothing was made regarding the splash screen.&lt;br&gt;
This is how it's displayed up to API level 30:&lt;/p&gt;

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

&lt;p&gt;As we didn't add nothing to set up a splash screen yet, a black screen is shown while the main activity is loading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important: On an Android 12, a static branded splash screen was automatically displayed, using a centered app icon without any effort at all. Nice improvement!&lt;/strong&gt;&lt;/p&gt;


&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fanimated_splash_guide%2Fandroid12_no_splash.jpg" width="800" height="400"&gt;
Automatic static splash screen on Android 12

&lt;h6&gt;
  
  
  To repeat this step, clone the following branch in Github's repo: &lt;a href="https://github.com/tgloureiro/animated_splashscreen_android/tree/step1_no_splash" rel="noopener noreferrer"&gt;github.com/tgloureiro/animated_splashscreen_android/tree/step1_no_splash&lt;/a&gt;
&lt;/h6&gt;
&lt;h1&gt;
  
  
  Showing a splash screen (Old way)
&lt;/h1&gt;

&lt;p&gt;The traditional way of defining a splash screen in Android, is setting a window background to the the activity being launched. As the content is not attached to it yet, the window background is fully visible while the activity is loading.  After it loads, content view is set inside the &lt;code&gt;onCreate()&lt;/code&gt; method and it's views starts being rendered.&lt;/p&gt;

&lt;p&gt;Therefore, to show the splash screen we have to set up the window background in the theme being used by the activity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;/res/values/themes.xml
&lt;span class="nt"&gt;&amp;lt;resources&lt;/span&gt; &lt;span class="na"&gt;xmlns:tools=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/tools"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Base application theme. --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Theme.AnimatedSplashScreen"&lt;/span&gt; 
        &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"Theme.MaterialComponents.DayNight.NoActionBar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Drawable to be rendered in window's background 
             while the activity is being loaded --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"android:windowBackground"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            @drawable/your_splashscreen_drawable
        &lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we need the splash screen to have a logo centered over some background drawable, we can use a &lt;code&gt;LayerDrawable&lt;/code&gt;, that allows us to specify a list of drawables that is drawn in the order they're declared. In this example, we have a flat colored background with the logo centered in the screen. The use of &lt;code&gt;android:gravity&lt;/code&gt; informs the platform to center the second drawable in the middle of the screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;/res/drawable/splash_screen.xml
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;layer-list&lt;/span&gt; &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;android:drawable=&lt;/span&gt;&lt;span class="s"&gt;"@drawable/splash_background"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;android:gravity=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt; 
        &lt;span class="na"&gt;android:drawable=&lt;/span&gt;&lt;span class="s"&gt;"@drawable/splash_logo"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/layer-list&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the splash background, we can use any type of drawable. For this example, we'll use a solid color. The color can be specified directly in the layer list, instead of pointing to another Drawable as we did here&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;/res/drawable/splash_screen.xml
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;shape&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;android:shape=&lt;/span&gt;&lt;span class="s"&gt;"rectangle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;solid&lt;/span&gt; &lt;span class="na"&gt;android:color=&lt;/span&gt;&lt;span class="s"&gt;"@color/blue"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/shape&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the old way of doing a splash screen and it's recommended up to API Level 22, the ones not covered by the new Core Splash Screen API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fading out the logo
&lt;/h2&gt;

&lt;p&gt;There's an easy way of implementing the splash screen's fade out after activity loading: we can have the illusion of a logo fade out making a cross-fade between the splash screen and the screen background without the logo. We can do it using a &lt;code&gt;TransitionDrawable&lt;/code&gt;. A transition drawable allows us to define two drawable layers and easily cross-fade between them using the &lt;code&gt;startTransition(int)&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;/res/drawable/splash_transition.xml
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;transition&lt;/span&gt; 
    &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;android:drawable=&lt;/span&gt;&lt;span class="s"&gt;"@drawable/splash_screen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;android:drawable=&lt;/span&gt;&lt;span class="s"&gt;"@drawable/splash_background"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/transition&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to perform the following tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check if the splash screen was not displayed, otherwise we just set content view&lt;/li&gt;
&lt;li&gt;Get a reference to the window background and start the crossfade transition&lt;/li&gt;
&lt;li&gt;Launch a coroutine and after waiting for the animation duration, set the content view
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;MainActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kt&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// Checks if the splash screen was displayed before&lt;/span&gt;
      &lt;span class="c1"&gt;// -&amp;gt;SavedInstanceState is not null after recreation!&lt;/span&gt;
      &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;splashWasDisplayed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;savedInstanceState&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;splashWasDisplayed&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="c1"&gt;// 1 - Start fading out the logo&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decorView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;background&lt;/span&gt; 
              &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;TransitionDrawable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="n"&gt;logoCrossFadeDurationMillis&lt;/span&gt;
              &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="c1"&gt;// 2 = As we can't register a listener to be &lt;/span&gt;
          &lt;span class="c1"&gt;// notified when the transition drawable finishes,&lt;/span&gt;
          &lt;span class="c1"&gt;// launches a coroutine that blocks while animation&lt;/span&gt;
          &lt;span class="c1"&gt;// is being performed and sets the content view&lt;/span&gt;
          &lt;span class="n"&gt;lifecycleScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="c1"&gt;// Time between the animations&lt;/span&gt;
              &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logoCrossFadeDurationMillis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;spacingAfterFadeDurationMillis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decorView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                &lt;span class="nc"&gt;AppCompatResources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDrawable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drawable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splash_background&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// Splash was shown before, no need to animate it.&lt;/span&gt;
          &lt;span class="c1"&gt;// 1 - Updates the window background (if needed)&lt;/span&gt;
          &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decorView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
            &lt;span class="nc"&gt;AppCompatResources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDrawable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drawable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splash_background&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="c1"&gt;// 2 - Sets the content view instantly&lt;/span&gt;
          &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check how it is rendered in a phone:&lt;/p&gt;

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

&lt;h6&gt;
  
  
  To repeat this step, clone the following branch in Github's repo: &lt;a href="https://github.com/tgloureiro/animated_splashscreen_android/tree/step2_fade_out_splash" rel="noopener noreferrer"&gt;github.com/tgloureiro/animated_splashscreen_android/tree/step2_fade_out_splash&lt;/a&gt;
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Showing the splash screen using Core SplashScreen API
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;Core Splash Screen API&lt;/strong&gt; provides a way of defining the elements we have in the Splash Screen. To setup a splash screen, you have to do the following steps:&lt;/p&gt;

&lt;p&gt;1- Setup a style with Theme.SplashScreen as a parent, in themes.xml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;themes.xml
    ...
    &lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Theme.AppSplash"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"Theme.SplashScreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Setup windowSplashScreenBackground, windowSplashScreenAnimatedIcon as the background and the centered logo in the screen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;themes.xml
    ...
    &lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Theme.AppSplash"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"Theme.SplashScreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"windowSplashScreenBackground"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@drawable/your_background_drawable&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"windowSplashScreenAnimatedIcon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@drawable/your_icon_drawable&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Setup the theme to be displayed in activity after the splash screen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;themes.xml
    ...
    &lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Theme.AppSplash"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"Theme.SplashScreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"windowSplashScreenBackground"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@drawable/your_background_drawable&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"windowSplashScreenAnimatedIcon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@drawable/your_icon_drawable&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"postSplashScreenTheme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@style/your_activity_theme&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- In build.gradle, change your compileSdkVersion to "android-S" (to be changed to apiLevel 31 with the release of Android 12) and include the library in dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;compileSdkVersion&lt;/span&gt; &lt;span class="s2"&gt;"android-S"&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'androidx.core:core-splashscreen:1.0.0-alpha01'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5- Finally, in the MainActivity (or the entry point for your app) you just have to call &lt;code&gt;installSplashScreen()&lt;/code&gt; before  &lt;code&gt;setContentView()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Very straightforward, huh? With these simple steps you'll be showing your splash screen from API23 to Android12.&lt;/p&gt;

&lt;h1&gt;
  
  
  Core SplashScreen API + Animations
&lt;/h1&gt;

&lt;p&gt;In Android 12, the logo itself can be animated using &lt;code&gt;AnimationDrawable&lt;/code&gt; or &lt;code&gt;AnimatedVector&lt;/code&gt;. The &lt;code&gt;AnimationDrawable&lt;/code&gt; works similar to a classical animation which you have to represent &lt;br&gt;
frame by frame and duration for each one. &lt;code&gt;AnimatedVectorDrawable&lt;/code&gt; let's you describe your animation that will be interpolated by the framework.&lt;/p&gt;

&lt;p&gt;The backported version of the &lt;strong&gt;Core Splash Screen API&lt;/strong&gt; doesn't support animations on the logo yet. But we can implement a fadeout animation after splash's exhibition and I'll show how to implement it using this API.&lt;/p&gt;

&lt;p&gt;We have to perform the following tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check if the splash screen was not displayed, otherwise we manually set the theme and the content view&lt;/li&gt;
&lt;li&gt;Install the splash screen and listen for the ExitAnimation event&lt;/li&gt;
&lt;li&gt;Get a reference to the the logo, fade it out, remove the splash and set content view after it finishes
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;MainActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kt&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;splashFadeDurationMillis&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;splashWasDisplayed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;savedInstanceState&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;splashWasDisplayed&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;splashScreen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;installSplashScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;splashScreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOnExitAnimationListener&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                &lt;span class="n"&gt;splashScreenViewProvider&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="c1"&gt;// Get logo and start a fade out animation&lt;/span&gt;
                &lt;span class="n"&gt;splashScreenViewProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iconView&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;splashFadeDurationMillis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withEndAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// After the fade out, remove the &lt;/span&gt;
                        &lt;span class="c1"&gt;// splash and set content view&lt;/span&gt;
                        &lt;span class="n"&gt;splashScreenViewProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Theme_AnimatedSplashScreen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Check how it is rendered in a phone:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h6&gt;
  
  
  To repeat this step, clone the following branch in Github's repo: &lt;a href="https://github.com/tgloureiro/animated_splashscreen_android/tree/step3_core_splash_api_fade_out" rel="noopener noreferrer"&gt;github.com/tgloureiro/animated_splashscreen_android/tree/step3_core_splash_api_fade_out&lt;/a&gt;
&lt;/h6&gt;
&lt;h1&gt;
  
  
  Showing the splash screen using Core SplashScreen API with Jetpack Compose
&lt;/h1&gt;

&lt;p&gt;The splash steps are pretty much the same, except we use Compose's &lt;code&gt;setContent{}&lt;/code&gt; instead of &lt;code&gt;setContentView(int)&lt;/code&gt;. That's it.&lt;/p&gt;

&lt;p&gt;The challenge here is to replace the start screen animation, originally made using MotionLayout, with one made using Compose. We can use an initially invisible AnimatedVisibility Composable and make it visible in the first pass using a LaunchedEffect. Making it visible will start the animation as described in the widget.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;MainActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kt&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;StartScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;visible&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="nf"&gt;colorResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;AnimatedVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;enter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;slideInVertically&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;initialOffsetY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="c1"&gt;// Slide in from top&lt;/span&gt;
                            &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="n"&gt;animationSpec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                          &lt;span class="n"&gt;durationMillis&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                          &lt;span class="nc"&gt;MainActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splashFadeDurationMillis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;easing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LinearEasing&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                            &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;horizontalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                            &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterHorizontally&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;
                            &lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="nf"&gt;colorResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="nf"&gt;stringResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_screen_title&lt;/span&gt;
                            &lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="n"&gt;fontSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                                &lt;span class="nf"&gt;dimensionResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dimen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_content_title_margin_bottom&lt;/span&gt;
                                    &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;White&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;fontWeight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FontWeight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bold&lt;/span&gt;
                        &lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="nf"&gt;dimensionResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dimen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_content_size&lt;/span&gt;
                                        &lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dimensionResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dimen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_content_size&lt;/span&gt;
                                    &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="nc"&gt;RoundedCornerShape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;
                                    &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;White&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check how it is rendered in a phone:&lt;/p&gt;

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

&lt;h6&gt;
  
  
  To repeat this step, clone the following branch in Github's repo: &lt;a href="https://github.com/tgloureiro/animated_splashscreen_android/tree/step4_core_splash_jetpack" rel="noopener noreferrer"&gt;github.com/tgloureiro/animated_splashscreen_android/tree/step4_core_splash_jetpack&lt;/a&gt;
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;The new Jetpack Core Splashscreen API provides a default way to create splash screens back to API23, with useful mechanisms we can use to know whether the loading ended and a way to continue showing the splash if we want to do additional work after starting the activity. The results are similar to what we had before, with the benefit of reduced boilerplate and compatibility with new Android versions. &lt;/p&gt;

</description>
      <category>android</category>
      <category>splash</category>
      <category>jetpack</category>
      <category>core</category>
    </item>
    <item>
      <title>Kotlin Multiplatform vs Flutter: Which One to Choose for Your Apps</title>
      <dc:creator>Tiago Loureiro</dc:creator>
      <pubDate>Tue, 20 Apr 2021 15:40:49 +0000</pubDate>
      <link>https://dev.to/tgloureiro/kotlin-multiplatform-vs-flutter-which-one-to-choose-for-your-apps-51oj</link>
      <guid>https://dev.to/tgloureiro/kotlin-multiplatform-vs-flutter-which-one-to-choose-for-your-apps-51oj</guid>
      <description>&lt;p&gt;Kotlin Multiplatform and Flutter are two of the hottest multi/cross-platform app frameworks and are maturing quite fast. Both help you to reuse code when developing apps for Android and iOS. However, these platforms are very different and serve distinct purposes. Having worked with both, I'm going to share what I consider to be each one's strengths and weaknesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin Multiplatform Mobile (KMM)
&lt;/h2&gt;

&lt;p&gt;Kotlin is a great choice for developing mobile apps. Its conciseness, simplicity, and expressivity allow you to write correct and readable code effortlessly. Kotlin is the suggested language if you are starting a new native Android Project. Hence, if you have to target Android devices, you will probably end with the Android business logic written in Kotlin. Now, imagine being able to put your Android's business logic code, almost untouched, inside your iOS project as an iOS Framework. KMM is the best tool to do this right now and is being used by companies like VMware, Philips, and Netflix.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.tiagoloureiro.tech%2F%2Fkmmexample.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.tiagoloureiro.tech%2F%2Fkmmexample.svg" alt="Kotlin Multiplatform Mobile code reuse" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In KMM, you have a shared folder that is completely reused between platforms. Most of the business logic will be platform-independent. But, when you need to write code that depends on native/system libraries, you can count with KMM's &lt;strong&gt;expect/actual&lt;/strong&gt; keywords.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With this mechanism, a common source set defines an expected declaration, and platform source sets must provide the actual declaration that corresponds to the expected declaration. This works for most Kotlin declarations, such as functions, classes, interfaces, enumerations, properties, and annotations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Curious for how it works? Look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Shared (Common)
expect fun randomUUID(): String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Android
import java.util.*
actual fun randomUUID() = UUID.randomUUID().toString()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// iOS
import platform.Foundation.NSUUID
actual fun randomUUID(): String = NSUUID().UUIDString()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Available in &lt;a href="https://kotlinlang.org/docs/mpp-connect-to-apis.html" rel="noopener noreferrer"&gt;kotlinlang.org/docs&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Very straightforward, right? This way, the randomUUID() function can be used from reused code (common code), with the correct implementation being provided for each platform during compilation. Then, common code is provided for each platform as an Android module or iOS Framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flutter
&lt;/h2&gt;

&lt;p&gt;Flutter is a cross-platform framework to target iOS and Android with a single codebase. Google calls it a "UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop". One of the superpowers of Flutter is that you can design almost any interaction or animation and have it running the same way in Android and iOS. No need to make special adjustments or to recreate the designed user interface using native platforms. For those who are looking to innovate in UI space or don't need to make strong use of native features, Flutter is a strong choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.tiagoloureiro.tech%2Fflutter_platforms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.tiagoloureiro.tech%2Fflutter_platforms.png" alt="Flutter platforms" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To write Flutter apps, you need to program in Dart. Dart is a C/Javascript/Java-like programming language, that may be very familiar if you have previous contact with some of these languages. New features like sound null safety makes Dart even closer to Kotlin and Swift. But make no mistake: to have modern language features like sealed classes, inline classes you may need to use code generators (Take a look at Remi Rousselet's &lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;Freezed&lt;/a&gt; as an example of generated code in Flutter).&lt;/p&gt;

&lt;p&gt;Flutter is very easy to use and has a really fast hot reload. It is nice to see your mobile UI rendered in almost real-time in an emulator/simulator as you code. It's not the best choice if you depend heavily on native features that don't have an existing library, because otherwise you may have to spend a lot of time making plumbing code for Flutter's platform channel. Another weakness is that the native UI components are recreated in Flutter's engine. This means that if a new OS version is released with new UI components, you will have to wait until Flutter catches up to use the newest resources.&lt;/p&gt;

&lt;h1&gt;
  
  
  My experience with KMM and Flutter in a real world project
&lt;/h1&gt;

&lt;p&gt;Yes, you're reading right. I worked with KMM for shared business logic between iOS and Android + Flutter for UI in a real-world app, that is yet to be launched. That way, we unified our low-level network code and business logic between platforms with KMM, leaving Flutter with only the UI layer of the app. I will detail the design decisions and how everything went in a next post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one should I choose? Summary:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Kotlin Multiplatform Mobile may be a good choice if...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Already have existing native-specific code to be reused.&lt;/li&gt;
&lt;li&gt;You care about having the most updated native components and want to have a 100% native look and feel on every new OS version.&lt;/li&gt;
&lt;li&gt;You want to incrementally share code between platforms on an existing codebase.&lt;/li&gt;
&lt;li&gt;You don't need to publish a desktop or web version of your app.&lt;/li&gt;
&lt;li&gt;You don't want to depend on Flutter engine's implementation on each platform.&lt;/li&gt;
&lt;li&gt;Your project isn't going to be released very soon, or you don't mind about KMM being in alpha status right now.&lt;/li&gt;
&lt;li&gt;Your app is strongly tied to multi-thread or it has background processing needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Beware: KMM is currently in alpha and the APIs may change until it hits stable. Kotlin native  memory management is being replaced (important for iOS). You will need to study how it handles memory management, concurrency and immutability to correctly implement multiplatform code for now. Check: &lt;a href="https://kotlinlang.org/docs/native-concurrency.html#global-variables-and-singletons" rel="noopener noreferrer"&gt;https://kotlinlang.org/docs/native-concurrency.html#global-variables-and-singletons&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Flutter may be a good choice if...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You are in a small team and don't have resources for two native UI codebases.&lt;/li&gt;
&lt;li&gt;Your app depends mostly on simple API and database calls, a common use case in mobile apps. In this scenario, you can avoid writing Flutter's Platform Channel code as you won't need to interact with native code.&lt;/li&gt;
&lt;li&gt;Your app has a custom UI or you are innovating in UI space.&lt;/li&gt;
&lt;li&gt;You target Web and Desktop besides Mobile and want to have a working solution for these platforms right now.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kotlinmultiplatform</category>
      <category>flutter</category>
      <category>kotlin</category>
      <category>kmm</category>
    </item>
    <item>
      <title>Updating your Android toolbox: what should I learn for Android development in 2021?</title>
      <dc:creator>Tiago Loureiro</dc:creator>
      <pubDate>Tue, 20 Apr 2021 13:40:09 +0000</pubDate>
      <link>https://dev.to/tgloureiro/updating-your-android-toolbox-what-should-i-learn-for-android-development-in-2021-3c63</link>
      <guid>https://dev.to/tgloureiro/updating-your-android-toolbox-what-should-i-learn-for-android-development-in-2021-3c63</guid>
      <description>&lt;p&gt;This week marks the first beta release of &lt;a href="https://developer.android.com/jetpack/compose" rel="noopener noreferrer"&gt;Jetpack Compose&lt;/a&gt;. Seeing those platform changes happening, I curated recommended technologies, libraries, and frameworks to be used in new projects, based on my previous experience, gut feelings, and everything that is being released right now. For now, I'm citing the topics and later each one will become a thorough and independent article in this blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fkotlin_android.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fkotlin_android.jpeg" alt="Kotlin loves Android" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kotlin is an exciting programming language designed to be concise and expressive. It's Google's recommended programming language for Android since 2019 and has great tooling support on Android Studio. Kotlin allows the programmer to write safer code and android apps written in Kotlin are 20% less likely to crash (compared to old Java versions), thanks to features like type and null safety. It combines aspects of object-oriented and functional programming paradigms to allow the programmer to write better code.&lt;/p&gt;

&lt;p&gt;Access &lt;a href="https://developer.android.com/kotlin/first" rel="noopener noreferrer"&gt;https://developer.android.com/kotlin/first&lt;/a&gt; to start learning Kotlin-first Android development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android Jetpack
&lt;/h2&gt;

&lt;p&gt;Historically, Android wasn't an opinionated platform, regarding app architecture and modularization. Things like backward compatibility, navigation, state management, and app lifecycle were error-prone and slowed app development. Hence, the Android team decided to create a suite of libraries to help developers write code that follows best practices, with less boilerplate, and is consistent across Android versions and devices. &lt;/p&gt;

&lt;p&gt;Some of the libraries, like Jetpack's LiveData and Databinding were a first step towards declarative UI. They're now being replaced with better alternatives like Compose UI and Flow, and albeit they're practically alpha, it's not recommended anymore to be used in new projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beware&lt;/strong&gt;: You're about to meet some Android Studio bugs and Compose UI tooling issues while using Android Studio Canary. But that's ok, they're expected to be polished throughout the year and aren't blocking the work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;These are the up to date, recommended Jetpack libraries to be used in new projects:&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Jetpack Compose
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fcompose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fcompose.png" alt="Jetpack Compose logo" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jetpack Compose is a declarative, modern approach for building user interfaces in Android and is intended to replace the old way of doing Android UI. It allows you to build UI without the need to mutate the views whenever data changes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"In Compose's declarative approach, widgets are relatively stateless and do not expose setter or getter functions."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that the UI &lt;strong&gt;observes&lt;/strong&gt; a state and all the screen is regenerated based on any changes on this state. The smartness here is that Compose knows which view must be updated, and only redraws the necessary portion of the screen, avoiding excessive calculations.&lt;/p&gt;

&lt;p&gt;It has special tooling available in Android Studio preview, like smart editor features and Compose UI preview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fcomposeuisamples.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fcomposeuisamples.png" alt="Compose UI samples" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get started on &lt;a href="https://developer.android.com/jetpack/compose" rel="noopener noreferrer"&gt;https://developer.android.com/jetpack/compose&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.  ViewModel
&lt;/h3&gt;

&lt;p&gt;One of the most important concepts needed to develop an Android App is the concept of the lifecycle. In the platform, every main building block has a lifecycle that is controlled mainly by the operating system. So, your app isn't really creating an Activity or a Fragment by itself, it is asking the OS to provide an instance of one or another. When the system has a memory pressure, it starts releasing resources and a part (or the whole) of your app may be destroyed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Doing the right work at the right time and handling transitions properly make your app more robust and performant. For example, good implementation of the lifecycle callbacks can help ensure that your app avoids:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crashing if the user receives a phone call or switches to another app while using your app.&lt;/li&gt;
&lt;li&gt;Consuming valuable system resources when the user is not actively using it.&lt;/li&gt;
&lt;li&gt;Losing the user's progress if they leave your app and return to it at a later time.&lt;/li&gt;
&lt;li&gt;Crashing or losing the user's progress when the screen rotates between landscape and portrait orientation."&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand why ViewModel was proposed and how it works, just look at the lifecycle of a ViewModel side by side with the Activity lifecycle.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fviewmodel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fviewmodel.png" alt="ViewModel lifecycle" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ViewModel survives configuration changes and is only released when the Activity is finished. Another important usage of a ViewModel, is when you need to share state between Fragments. A ViewModel can outlive each of the Fragments, with its scope bound to the lifecycle of the enclosing Activity.&lt;/p&gt;

&lt;p&gt;The ViewModel name comes from an architectural pattern called MVVM (Model-View-ViewModel). Architectural patterns are ways of organizing your code to achieve higher maintainability of your software in the long run. Different patterns arise accordingly to the task being executed, platform, team's size, and other characteristics of the project. I intend to discuss these architectural topics on this blog in the future.&lt;/p&gt;

&lt;p&gt;Learn how to create and use a ViewModel in &lt;a href="https://developer.android.com/topic/libraries/architecture/viewmodel" rel="noopener noreferrer"&gt;https://developer.android.com/topic/libraries/architecture/viewmodel&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3.  Room
&lt;/h3&gt;

&lt;p&gt;Using relational databases is an important part of developing applications. Android traditionally has good support for SQLite, a lightweight database manager. SQlite is very useful for persisting and organizing non-volatile data, but to use it you have to face some challenges. It's low-level APIs demands a lot of the developer's time to be used and maintained:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;"There is no compile-time verification of raw SQL queries. As your data graph changes, you need to update the affected SQL queries manually. This process can be time-consuming and error-prone."&lt;/li&gt;
&lt;li&gt;"You need to use lots of boilerplate code to convert between SQL queries and data objects."&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Room persistence library was created as an abstraction layer that allows developers to have compile-time verification of SQL queries, annotations to reduce boilerplate code, and tools to ease database migrations.&lt;/p&gt;

&lt;p&gt;Example of a User Data Access Object with its annotations. Note that insert and delete annotations didn't require writing SQL queries by hand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List&amp;lt;User&amp;gt;

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List&amp;lt;User&amp;gt;

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Room's training on developer.android.com: &lt;a href="https://developer.android.com/training/data-storage/room" rel="noopener noreferrer"&gt;https://developer.android.com/training/data-storage/room&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Paging v3
&lt;/h3&gt;

&lt;p&gt;Whenever you have lots of data coming from a data source, be it an API or a database, usually some kind of pagination is needed to meet speed and bandwidth requirements, for instance. With pagination, only a subset of the data is served (and rendered), and the user can ask for more data later if needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The components of the Paging library are designed to fit into the recommended Android app architecture, integrate cleanly with other Jetpack components, and provide first-class Kotlin support. The Paging library includes the following features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In-memory caching for your paged data. This ensures that your app uses system resources efficiently while working with paged data.&lt;/li&gt;
&lt;li&gt;Built-in request deduplication, ensuring that your app uses network bandwidth and system resources efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Configurable RecyclerView adapters that automatically request data as the user scrolls toward the end of the loaded data.&lt;/del&gt; (Recycler view isn't needed anymore on Jetpack Compose 🥳)&lt;/li&gt;
&lt;li&gt;First-class support for Kotlin coroutines and Flow, as well as LiveData and RxJava.&lt;/li&gt;
&lt;li&gt;Built-in support for error handling, including refresh and retry capabilities."&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following diagram illustrates how Paging fits into the typical architecture of an Android application. Now that we have Jetpack Compose, the PagingDataAdapter is not needed anymore, a composable function watches PagingData state on ViewModel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fpagingarch.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftiagoloureiro.tech%2Fpagingarch.svg" alt="Paging architecture" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paging v3 library documentation: &lt;a href="https://developer.android.com/topic/libraries/architecture/paging/v3-overview" rel="noopener noreferrer"&gt;https://developer.android.com/topic/libraries/architecture/paging/v3-overview&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Navigation
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;In the beginning, the Android team created the Activity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before Android 3.0 (Honeycomb), the typical android app worked swapping activities and asking for third-party activities to be displayed by the operating system. With the arrival of Android tablets, this abstraction wasn't sufficient anymore. Usually, a tablet can show master and detail views simultaneously, and rewriting the whole app for tablets wasn't an option. Hence, Fragments were created with the mission to be autonomous and combined within Activities, which acted as a wrapper for one or more fragments. The navigation now was mainly changing between app fragments. Any app that has more than one screen needs some type of navigation system, even if done manually without any tooling help.&lt;/p&gt;

&lt;p&gt;Navigation on Android isn't a simple task. Managing aspects like the &lt;em&gt;up button™&lt;/em&gt; and &lt;em&gt;back button™&lt;/em&gt;, deep linking, fragment transactions and animated transitions, fragment arguments, and a plethora of specificities can be hard. Jetpack Navigation helps to implement navigation in a correct and principled way.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;New:&lt;/em&gt; On Jetpack Compose, you can project your UI without using Fragments, View, and XML files. Everything is done on Kotlin, including navigation with NavHost and NavController.&lt;/p&gt;

&lt;p&gt;Learn to use Navigation with Compose in &lt;a href="https://developer.android.com/jetpack/compose/navigation" rel="noopener noreferrer"&gt;https://developer.android.com/jetpack/compose/navigation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hint:&lt;/strong&gt; The documentation doesn't include the imports needed to complete the training. As navigate(route:String) is an extension function (not included by default in NavController), you may need to add the following import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import androidx.navigation.compose.navigate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using &lt;code&gt;popUpTo(route:String)&lt;/code&gt;, you need to add the second argument &lt;code&gt;inclusive: Boolean&lt;/code&gt; that isn't cited in the official documentation. So your code will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Pop everything up to the "home" destination off the back stack before
// navigating to the "friends" destination
navController.navigate(“friends”) {
    popUpTo("home") { inclusive = false }
}

// Pop everything up to and including the "home" destination off
// the back stack before navigating to the "friends" destination
navController.navigate("friends") {
    popUpTo("home") { inclusive = true }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Hilt (Jetpack)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Hilt is a dependency injection library for Android that reduces the boilerplate of doing manual dependency injection in your project. Doing manual dependency injection requires you to construct every class and its dependencies by hand, and to use containers to reuse and manage dependencies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;1.Why dependency injection (DI)?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;R. DI makes unit testing easier, as it allows the &lt;strong&gt;injection&lt;/strong&gt; of test doubles instead of implementations. Also, it helps reduce coupling, because it forces the developer to program for an interface, instead of an implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Why coupling is bad?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;R. Because the code you make today will have to be changed, adapted, maintained by someone (or yourself). When your code is tightly coupled, refactors are hard and any small change may break your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Does DI cause any adverse effects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;R. Debugging can be harder, because of all the indirections caused by the presence of a dependency injection system. Many DI frameworks have a steep learning curve, a considerable barrier to beginners.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hilt provides a standard way to use DI in your application by providing containers for every Android class in your project and managing their lifecycles automatically. Hilt is built on top of the popular DI library Dagger to benefit from the compile-time correctness, runtime performance, scalability, and Android Studio support that Dagger provides. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hilt documentation: &lt;a href="https://developer.android.com/training/dependency-injection/hilt-android" rel="noopener noreferrer"&gt;https://developer.android.com/training/dependency-injection/hilt-android&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>jetpack</category>
    </item>
  </channel>
</rss>
