Reputation: 1842
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.
Upvotes: 4
Views: 892
Reputation: 1923
"This looks like an Architectural Problem."
Calling an API into application class and registering it's listener to your activities is a bad idea!
There are few options for you to handle your requirement:
What will happen if process restarts in this case?
Your MainActivity will recreate and call the API again. So, you're good.
What will happen if process restarts in this case?
Since you've already cached your data into a persitent storage, it'll be there even after process restart. So, you're good to get your data back.
Bonus
If you don't want to use your cached data everytime you open your app, just clear the cache in your SplashActivity and call the API everytime to have the latest data with you before moving to MainActivity.
Upvotes: 2
Reputation: 1022
You will have to handle this in your onResume() lifecycle. You can create an onResume and then call the SplashActivity intent and finish() your MainActivity. This way it will just go back to Splash Screen where it will load the data and call the Main Activity again
override fun onResume() {
super.onResume()
val intent = Intent(this,SplashActivity)
startActivity(intent)
}
Upvotes: 2