Creating a Splash Screen in Android : Part 2

Chintan Soni
Simform Engineering
3 min readApr 30, 2019
Interesting Splash Screen motion design by Parva Studio

Hello folks, we are here again, to take one more step to improve our Splash Screen. In my previous article, we learnt how beautifully we used the delay caused by Android system in launching our apps, and created a smooth User Experience. In this article, we are gonna talk on what if User navigates away from your app, while your app is still at Splash Screen.

Lets say, your Splash screen creates a delay of 3 seconds and then it has to navigate to Home screen. Now, what if User presses Home button during that moment ? (may be to earn some bug bounty 😉). Now what!!

Yeah, this is an average developer’s nightmare! 😁

What a developer can choose to do ?

Unhandled situation:

When User navigates away during Splash delay period, lets say User minimized your app and opened Instagram, after delay period is over, your app will interrupt User’s experience, because while User is using Instagram, your app will appear suddenly out of no where! Very bad!!👎🏻👎🏻

Poorly handled situation:

Cancel that network call in Activity’s onStop() and restart it in onStart()

But this fix makes UX even worse:
1. A total wasted network call
2. And now, User has to wait 3 seconds, again!
Still, not an acceptable solution!👎🏻

Smartly handled situation:

Leverage the power of Architecture Components! 😇
Lets understand the duo of LiveData and ViewModel.

LiveData: It is kinda Observable but Life-cycle aware. Their Observers gets triggered (Notified) only when Activity (or Fragment) is in Foreground. When your Activity (or Fragment) enters Background, doesn’t notify their Observer for updates and instead, it stores the updates to itself. Later, when Activity (or Fragment) returns to Foreground and observers are active again, they receive the last update from LiveData. How amazing!

ViewModel: It is kinda Singleton container. It stores data within it across Activity (or Fragment) Life-cycle. It gets cleared only when the component it is attached with gets Finished (or Destroyed).

Now, lets get into some code and create a ViewModel as:

class SplashViewModel : ViewModel() {    val liveData: LiveData<SplashState>
get() = mutableLiveData
private val mutableLiveData = MutableLiveData<SplashState>()
init {
GlobalScope.launch {
delay(3000)
mutableLiveData.postValue(SplashState.MainActivity())
}
}
}
sealed class SplashState {
class MainActivity : SplashState()
}

I created and exposed a liveData publicly that will be observed by my SplashActivity. This liveData emits data of type SplashState.

Next, we have created a sealed class (equivalent to enum in Java) SplashState that represents state of any activity. Moreover, I have used Coroutines to simplify the splash “delay” stuff.

Lets take a look in SplashActivity:

lass SplashActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)

val splashViewModel = ViewModelProviders.of(this).get(SplashViewModel::class.java)
splashViewModel.liveData.observe(this, Observer {
when (it) {
is SplashState.MainActivity -> {
goToMainActivity()
}
}
})
}

private fun goToMainActivity() {
finish()
startActivity(Intent(this, MainActivity::class.java))
}
}

SplashActivity has initialized ViewModel SplashViewModel and has started observing liveData. Once, the delay of 3000 ms is over, liveData will post a SplashState of MainActivity, and as a result of update received in Observer, it will navigate to MainActivity. That’s it !!!

Benefits:

  1. Improved User Experience: Even if your User navigated to away from Splash within 3000 ms, and returns to your app after sometime in future, the progress will be saved and app will resume from the same point, an improved User Experience.
  2. Nicer coding practise: Wondering why we used two LiveData, it could have been done using just one MutableLiveData by making it public ? Its just that I simply restricted the View (here Activity) from being able to modify value of LiveData. Yes, you can only set values to LiveData that are instances of MutableLiveData or MediatorLiveData, and not the instance of the core LiveData class.

Guys, this code structure will help you take your first steps towards architecting your app with MVVM architecture. Soon, I am gonna throw more lights on how to think MVVM. Stay tuned!

That’s all folks! Hope you enjoyed learning with me. Do show your love by hitting Claps and share this article, if you loved it.

--

--

Chintan Soni
Simform Engineering

Engineering Manager | 10+ years of experience | Android | Angular | NodeJS | React | Docker