When I start ActivityMain
in Code 1, a service will be launched, and the service will be destroied after the ActivityMain
is destroied , you can see Image 1 for result, it’s just like my expected.
In Code 2, I hope to delay to destroy the service, but I find the onDestroy
event of a service isn’t launched in Code 2, you can see Image 2, why ?
BTW, After I l re-lauch Code 2, I find there is new hash value for the service, it seems that the service is destroied and re-created.
Code 1
class ActivityMain : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
serviceTranslateIntent = Intent(this, ServiceTranslate::class.java)
this.startService(serviceTranslateIntent)
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Create Activity" )
}
override fun onDestroy() {
super.onDestroy()
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Destroy Activity" )
this.stopService(serviceTranslateIntent)
}
}
class ServiceTranslate: Service() {
override fun onCreate() {
super.onCreate()
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Create Server" )
}
override fun onDestroy() {
super.onDestroy()
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Destroy Server" )
}
}
Code 2
class ActivityMain : ComponentActivity() {
// The same
override fun onDestroy() {
super.onDestroy()
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Destroy Activity" )
val aa = this
lifecycleScope.launch {
log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Destroy Scope" )
delay(5000)
aa.stopService(serviceTranslateIntent)
}
// I will get the same result with the code below
// val aa = this
// Handler().postDelayed({
// log(System.currentTimeMillis().toString()+" Hash: "+ this.hashCode()+" Destroy Scope" )
// aa.stopService(serviceTranslateIntent)
// }, 2000)
}
}
//The same
Image 1
Image 2
2
Answers
i think you should not handle asynchronous in onDestroy. If you want to turn off the timer to turn off the service, you can handle it right in the service
lifecycleScope
is bound to the scope of the Activity lifecycle, so when the Activity reaches the destroyed state, all of the CoroutineScope’s coroutines are cancelled, and new ones (like yours) won’t even start. Here is the documentation about it being cancelled when the destroyed state is reached.As for why it seems to have given you a new service instance on relaunch, it is possible your app completely relaunched since it was last on screen. There is not enough info provided to be sure what happened there, but I see the new activity was created 11 seconds since it was previously destroyed.
If you are simply backing out of the main activity so your app goes off screen, then it is probably killing your service instantly. Background services are not guaranteed to be kept alive while your app is off-screen. It might not even be calling your service’s
onDestroy()
if it’s just killing your app, although I wouldn’t expect this behavior to be likely on a modern device with such a low-memory app.