ByteCode, dedicated to share the latest technology original articles, involving Kotlin, Jetpack, translation, system source code, LeetCode/point Offer/multithreading/domestic and foreign large factory algorithm problems and so on a series of articles.

The Jetpack family has a new member, Core Splashscreen, so IT’s time for me to start the Jetpack series again, after writing a series of Jetpack articles and their accompanying apps, App Startup, Paging3, Hilt, DataStore, ViewBinding, etc. Click on the link below to check it out.

  • Androidx-jetpack-practice series of actual combat projects
  • The end of the Kotlin plugin and the rise of ViewBinding
  • Surprisingly simple, DataBinding and ViewBinding
  • Jetpack DataStore SharedPreferences
  • Jetpack DataStore (2)
  • AndroidX App Startup practice and principle analysis of Jetpack members
  • Jetpack member Paging3 Database practice and source code Analysis (1)
  • Jetpack Member Paging3 Network Practice and Principle Analysis (II)
  • Jetpack member Paging3 retrieves network page data and updates it to the database
  • Jetpack member Hilt practice (1) Start a pit
  • Jetpack member Hilt’s App Startup practice (2) Advanced part
  • Jetpack member Hilt has a different Dagger
  • All aspects of Hilt and Koin performance were analyzed
  • Jetpack: Pokemon

The Splashscreen API has been added to Android 12 to improve the user experience. It adds a Splashscreen to all applications. This includes a startup animation that enters the application at startup, as well as an exit animation.

Here’s what you’ll learn in this article

  • What problem does Core Splashscreen solve?
  • How does Core Splashscreen work?
  • How do you use Core Splashscreen in your projects for different scenarios?
  • Core Splashscreen source code analysis

Go to GitHub to see the sample project Splashscreen. Github.com/hi-dhl/Andr…

Core Splashscreen

What problem does Core Splashscreen solve?

In order to improve the experience, the startup screen is added to improve the visual experience. In order to achieve this function, there are many implementation methods in the market, all of which have their own advantages and disadvantages. Therefore, it is not guaranteed to run smoothly on all devices.

Secondly, sometimes it is necessary to load data asynchronously from the local disk or network and wait for the data to be loaded before rendering the View. Most of the time, it is hoped to load data in advance to ensure that users can see the data after entering the home page to reduce the waiting time of users.

The SplashScreen API, added to Android 12, addresses these issues, but is limited to Android 12.

The result was Core Splashscreen, which provides backward compatibility with the Splashscreen API added to Android 12, It works on all Android 5.0 (API 21) to Android 12 (API 31) apis. Take a look at the animation provided by Google.

How Core Splashscreen works

Core Splashscreen provides backward compatibility with the new Splashscreen API for Android 12, but the Splashscreen is only displayed when:

  • Cold start: The APP process is not running when the user opens the APP
  • Warm start: The APP process is running, but the Activity has not been created

The boot animation is displayed only in the above cases, but the boot screen is not displayed during hot boot.

  • Hot launch: The APP process is running and the Activity has been created, meaning that the user presses the Home button to go back to the background and no launch screen is displayed until the Activity is destroyed

How to use Core Splashscreen

Since Core Splashscreen is compatible with Android 12’s new Splashscreen API, you need to update compileSdkVersion to 31 or higher.

If your SDK has not been updated to Android 12, please do so first. SDK Manager -> Select Android 12

android {
    compileSdkVersion 31
}
Copy the code

Add the following dependencies to the build.gradle file at the module level.

Implementation 'androidx. Core: the core - splashscreen: 1.0.0 - alpha01'Copy the code

Once the dependency is added, you can start using Core Splashscreen, which displays the Splashscreen in just three steps.

1. Inres/values/themes.xmlAdd a new theme under the fileTheme.AppSplashScreen

<style name="Theme.AppSplashScreen" parent="Theme.SplashScreen"> <item name="windowSplashScreenBackground">@color/purple_200</item> <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item> <item name="postSplashScreenTheme">@style/Theme.AppTheme</item> </style> <! -- Base application theme. --> <style name="Theme.AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <! </style>Copy the code
  • android:windowSplashScreenBackground: Sets the background color
  • windowSplashScreenAnimatedIcon: Sets the icon displayed in the middle of the screen, if yesAnimationDrawableAnimatedVectorDrawableCreates an object that animates and plays the animation when the page is displayed
  • postSplashScreenTheme: Sets the display animation to use the APP’s default theme when it is not visible

In 2.applicationNode, set the topic added in the previous stepTheme.AppSplashScreen

<application
    android:theme="@style/Theme.AppSplashScreen">
</application>
Copy the code

3. In the callsetContentView()Method before callinginstallSplashScreen()

class MainActivity : AppCompatActivity() {
    private val binding: ActivityMainBinding by viewbind()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        installSplashScreen()
        with(binding) {
            // init view
        }
    }
}
Copy the code

Calling the installSplashScreen() method basically associates the Activity with the theme we added. Once this is done, you can see the icon or animation you just set during APP startup.

Extend the functionality

Make the startup animation last longer

By default, the splash screen will close immediately after the first frame is drawn, but in some cases, data needs to be loaded asynchronously from the local disk or network. In this case, you want the splash screen to wait until the data is loaded. This can be done in the following ways.

splashScreen.setKeepVisibleCondition { ! Handler(looper.getMainLooper ()).postdelayed ({appReady = true}, 3000).delay ({appReady = true}, 3000)Copy the code

By calling the above method, the application can pause the first frame so that the splash screen does not end, and when the data is loaded, it can control whether the splash screen ends by updating the variable appReady.

Implement exit animation

We can also add a splash screen exit animation, which gracefully returns from the splash screen to the app’s main screen.

splashScreen.setOnExitAnimationListener { splashScreenViewProvider -> ...... Val translationY = objectAnimator.offloat (......) translationY.doOnEnd { splashScreenViewProvider.remove() } translationY.start() }Copy the code

You can go to GitHub to see the sample project Splashscreen.

GitHub sample project: https://github.com/hi-dhl/AndroidX-Jetpack-Practice

Core Splashscreen source code parsing

The source code for Core Splashscreen is simple, with only two classes in total.

  • SplashScreen: Mainly provides backward compatibility for implementing the SplashScreen API to associate activities with themes.
  • SplashScreenViewProvider: Used to control the exit animation (splash screen -> application main screen), when the exit animation needs to be manually calledSplashScreenViewProvider#remove()methods

Initialize the SplashScreen

Initialize the Activity by calling the SplashScreen#installSplashScreen() method to associate it with the added theme. androidx/core/splashscreen/SplashScreen.kt

public companion object {
    @JvmStatic
    public fun Activity.installSplashScreen(): SplashScreen {
        val splashScreen = SplashScreen(this)
        splashScreen.install()
        return splashScreen
    }
}

private fun install() {
    impl.install()
}
Copy the code

The final initialization is done by calling the impl.install() method. Let’s see how the impl member variable is initialized.

private val impl = when {
    SDK_INT >= 31 -> Impl31(activity)
    SDK_INT == 30 && PREVIEW_SDK_INT > 0 -> Impl31(activity)
    SDK_INT >= 23 -> Impl23(activity)
    else -> Impl(activity)
}
Copy the code

At this point, we know that Google has different implementation classes for each version of the system for backward compatibility. The final initialization is done by calling the Install () method, which parses the added theme within install(), and finally associating the added theme with the activity with the activity.setTheme() method.

How to make the startup animation last longer

In the code, we make the start animation last a bit longer by calling SplashScreen#setKeepVisibleCondition() and wait for the data to finish. Let’s take a look at this method. androidx/core/splashscreen/SplashScreen.kt

public fun setKeepVisibleCondition(condition: KeepOnScreenCondition) {// impl: For different versions of the system, Respectively to have different implementation classes impl. SetKeepVisibleCondition (condition)} open fun setKeepVisibleCondition (keepOnScreenCondition: KeepOnScreenCondition) { ...... observer.addOnPreDrawListener(object : OnPreDrawListener { override fun onPreDraw(): Boolean { if (splashScreenWaitPredicate.shouldKeepOnScreen()) { return false } ContentView. ViewTreeObserver. RemoveOnPreDrawListener (this) / / when start drawing, will call dispatchOnExitAnimation method, End start animation mSplashScreenViewProvider? .let(::dispatchOnExitAnimation) return true } }) }Copy the code

Finally, the ViewTreeObserver listens for changes to the view and calls the OnPreDrawListener#onPreDraw() method when the view is about to start drawing. Finally, the dispatchOnExitAnimation method is called to end the startup animation.

Implement exit animation

Finally, let’s take a look at the source code is how to achieve exit animation, that is, from the startup screen gracefully back to the main application interface, the source code only provides an OnExitAnimationListener interface, will exit animation to the developer to implement, Look at the together SplashScreen# setOnExitAnimationListener () method. androidx/core/splashscreen/SplashScreen.kt

Android more than 12

override fun setOnExitAnimationListener(
    exitAnimationListener: OnExitAnimationListener
) {
    activity.splashScreen.setOnExitAnimationListener {
        val splashScreenViewProvider = SplashScreenViewProvider(it, activity)
        exitAnimationListener.onSplashScreenExit(splashScreenViewProvider)
    }
}
Copy the code

The Android interface is provided through the system source activity in 12. SplashScreen. SetOnExitAnimationListener, The callback to the exposed interface OnExitAnimationListener allows the developer to exit the animation.

Android under 12

open fun setOnExitAnimationListener(exitAnimationListener: OnExitAnimationListener) { animationListener = exitAnimationListener val splashScreenViewProvider = SplashScreenViewProvider(activity) ...... splashScreenViewProvider.view.addOnLayoutChangeListener( object : OnLayoutChangeListener { override fun onLayoutChange(......) {... dispatchOnExitAnimation(splashScreenViewProvider) } }) } fun dispatchOnExitAnimation(splashScreenViewProvider: SplashScreenViewProvider) { ...... splashScreenViewProvider.view.postOnAnimation { finalListener.onSplashScreenExit(splashScreenViewProvider) } }Copy the code

Through to the screen shown in the View of adding addOnLayoutChangeListener method to monitor the change of the layout, when layout will change, will callback onLayoutChange method, Finally, a callback to the exposed interface OnExitAnimationListener allows the developer to implement the exit animation.

However, it is important to note that the SplashScreenViewProvider#remove() method is always called to remove the animation when appropriate. This method can be called at the end of the exit animation.

conclusion

This article analyzes Core Splashscreen from different perspectives. To see how to use Core Splashscreen in your project, go to GitHub to see the sample project Splashscreen.

Warehouse address: https://github.com/hi-dhl/AndroidX-Jetpack-Practice

In addition, KtKit is a small utility library written in Kotlin language, which contains a series of tools commonly used in the project. I added many new features and included many Kotlin tricks. For article analysis, go to see Kotlin’s technique and analysis (3) that few people know about.

To monitor the EditText

Bind the Flow via lifecycleScope to the EditText and Activity/Fragment lifecycle. At the end of the Activity/Fragment lifecycle, When the flow ends, the reference between them is broken, effectively avoiding memory leaks.

. TextChange (lifecycleScope) {log.e (TAG, "TextChange = $it")} / / listening TextWatcher# beforeTextChanged callback function editText. TextChangeWithbefore (lifecycleScope) { Log.e(TAG, "TextChangeWithbefore = $it")} / / listening TextWatcher# afterTextChanged callback function editText. TextChangeWithAfter (lifecycleScope) { Log.e(TAG, "textChangeWithbefore = $it") } ......Copy the code

Monitor cellular network changes

lifecycleScope.launch {
    listenCellular().collect {
        Log.e(TAG, "listenNetwork = $it")
    }
}
Copy the code

Listen for changes to the wifi network

lifecycleScope.launch {
    listenWifi().collect {
        Log.e(TAG, "listenNetwork = $it")
    }
}
Copy the code

Monitor bluetooth network changes

lifecycleScope.launch {
    listenNetworkFlow().collect {
        Log.e(TAG, "listenNetwork = $it")
    }
}
Copy the code

Click here to see more API usage:

  • KtKit warehouse address: https://github.com/hi-dhl/KtKit
  • KtKit online: https://ktkit.hi-dhl.com

If this warehouse is helpful to you, please star for me at the upper right corner of the warehouse. Thank you very much for your support, and you are also welcome to submit PR ❤️❤️❤️


A “like” would be the biggest encouragement if it helps

More code, more articles

Welcome to the public account: ByteCode, continue to share the latest technology



Finally, I recommend the projects and websites I have been updating and maintaining:

  • Personal blog, will all articles classification, welcome to check hi-dhl.com

  • Androidx-jetpack-practice androidX-Jetpack-practice androidX-Jetpack-Practice androidX-Jetpack-Practice AndroidX-Jetpack-Practice

  • LeetCode/multiple thread solution, language Java and Kotlin, including a variety of solutions, problem solving ideas, time complexity, spatial complexity analysis

    • Job interview with major companies at home and abroad
    • LeetCode: Read online
  • Android10 Source code Analysis series of articles, understand the system Source code, not only help to analyze the problem, in the interview process, is also very helpful to us, the warehouse continues to update, welcome to check android10-source-Analysis

  • Collate and translate a series of selected foreign Technical articles, each Article will have a translator’s thinking part, a more in-depth interpretation of the original text, the warehouse continues to update, welcome to visit the Technical-Article-Translation

  • “Designed for Internet people, navigation of domestic and foreign famous stations” includes news, sports, life, entertainment, design, product, operation, front-end development, Android development and so on. Welcome to check the navigation website designed for Internet people

Article history

  • Kotlin’s Technique and Analysis (3)
  • Kotlin’s Technique and Principle Analysis that few people know (II)
  • Kotlin’s Technique and Principle Analysis that few people know (1)
  • Uncover the == and === in Kotlin
  • The Kotlin hermetic class evolved
  • The sealed class in Kotlin is superior to the tagged class
  • What is Kotlin Sealed? Why does Google use it all
  • Android 12 behavior changes that affect applications
  • AndroidStudio
  • Kotlin StateFlow search features practice DB + NetWork
  • The end of the Kotlin plugin and the rise of ViewBinding
  • Surprisingly simple, DataBinding and ViewBinding