Así que hay algunas cosas a tener en cuenta aquí, ya que hay muchas maneras de desollar a este gato. Aunque todas las respuestas ya han sido seleccionadas y elegidas. Creo que es importante que esto se revise con las pautas de codificación adecuadas para evitar que alguien vaya en la dirección incorrecta solo por la "respuesta simple seleccionada por la mayoría".
Primero, analicemos la respuesta simple Publicada diferida que es la respuesta seleccionada ganadora en general en este hilo.
Un par de cosas a tener en cuenta. Después de la demora posterior, puede encontrar fugas de memoria, objetos muertos, ciclos de vida que se han ido y más. Por lo tanto, manejarlo correctamente también es importante. Puedes hacer esto de dos maneras.
Por el bien del desarrollo moderno, suministraré en KOTLIN
Aquí hay un ejemplo simple de usar el hilo de la interfaz de usuario en una devolución de llamada y confirmar que su actividad todavía está viva y bien cuando golpea su devolución de llamada.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
Sin embargo, esto aún no es perfecto, ya que no hay razón para cancelar su devolución de llamada si la actividad ha desaparecido. así que una mejor manera sería mantener una referencia y eliminar sus devoluciones de llamada como esta.
private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.VISIBLE
mHandler.postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
}
}
y, por supuesto, manejar la limpieza en onPause para que no toque la devolución de llamada.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Ahora que hemos hablado a través de lo obvio, hablemos de una opción más limpia con las rutinas modernas y kotlin :). Si aún no los está utilizando, realmente se los está perdiendo.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
o si desea hacer siempre un inicio de UI en ese método, simplemente puede hacer:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Por supuesto, al igual que PostDelayed, debe asegurarse de manejar la cancelación para que pueda hacer las verificaciones de actividad después de la llamada de retraso o puede cancelarla en onPause al igual que la otra ruta.
var mDelayedJob: Job? = null
fun doActionAfterDelay()
mDelayedJob = launch(UI) {
try {
delay(MS_TO_DELAY)
actionToTake()
}catch(ex: JobCancellationException){
showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
}
}
}
}
// manejar la limpieza
override fun onPause() {
super.onPause()
if(mDelayedJob != null && mDelayedJob!!.isActive) {
A35Log.v(mClassTag, "canceling delayed job")
mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
}
}
Si coloca el inicio (UI) en la firma del método, el trabajo puede asignarse en la línea de código de llamada.
así que la moraleja de la historia es estar seguro con sus acciones retrasadas, asegurarse de eliminar sus devoluciones de llamada o cancelar sus trabajos y, por supuesto, confirmar que tiene el ciclo de vida correcto para tocar elementos en su devolución de llamada demorada completa. The Coroutines también ofrece acciones cancelables.
También vale la pena señalar que normalmente debe manejar las diversas excepciones que pueden venir con las corutinas. Por ejemplo, una cancelación, una excepción, un tiempo de espera, lo que decida usar. Aquí hay un ejemplo más avanzado si realmente decide comenzar a utilizar corutinas.
mLoadJob = launch(UI){
try {
//Applies timeout
withTimeout(4000) {
//Moves to background thread
withContext(DefaultDispatcher) {
mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
}
}
//Continues after async with context above
showFancyToast("Loading complete", true, FancyToast.SUCCESS)
}catch(ex: JobCancellationException){
showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
}catch (ex: TimeoutCancellationException) {
showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
}catch(ex: Exception){
showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
}
}