Say I have a custom application in class in my Android app that makes a network call, asynchronously, on startup. Then I have a Main activity that needs the results of the network call on startup. I can handle this with a Splash activity that waits on app startup. But when the process is recreated, we go straight to the Main activity, which expects the results of the network call to be there, and it crashes.
See the code below for an example.
What's the best way to handle this? I want to keep the splash screen for normal startup situations. But in the second situation, where the app is recreated, I'm not sure how to handle it. Is there a way to show the splash screen again, and wait, before returning to the recreated Main activity?
class MyApplication : Application() {
private val scope = CoroutineScope(Dispatchers.Main)
companion object {
lateinit var version: Integer
var startupFinishedListener: (() -> Unit)? = null
}
override fun onCreate() {
super.onCreate()
scope.launch {
version = getVersionFromNetwork() //Fake suspending network call
startupFinishedListener?.invoke()
}
}
}
class SplashScreen : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.splash)
MyApplication.startupFinishedListener = {
startMainActivity()
}
}
fun startMainActivity() {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
//This line will crash if we are coming from an activity recreation
Timber.d("Version is: ${MyApplication.version}")
}
}
I would prefer not to solve this by doing work in onResume
in all of my activities instead of onCreate()
. Ideally I could tell Android to launch my Splash activity before it launches the restored activity.