Portanto, existem algumas coisas a considerar aqui, pois existem muitas maneiras de esfolar esse gato. Embora todas as respostas já tenham sido dadas, foram selecionadas e escolhidas. Eu acho que é importante que isso seja revisado com diretrizes de codificação adequadas para evitar que alguém vá na direção errada apenas por causa da "resposta simples selecionada pela maioria".
Então, primeiro vamos discutir a resposta simples pós-adiada que é a resposta selecionada pelo vencedor em geral neste tópico.
Algumas coisas a considerar. Após o atraso da postagem, você poderá encontrar vazamentos de memória, objetos mortos, ciclos de vida que desapareceram e muito mais. Portanto, lidar com isso corretamente também é importante. Você pode fazer isso de duas maneiras.
Por uma questão de desenvolvimento moderno, fornecerei em KOTLIN
Aqui está um exemplo simples de como usar o encadeamento da interface do usuário em um retorno de chamada e confirmar que sua atividade ainda está ativa e bem quando você pressiona seu retorno de chamada.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
No entanto, isso ainda não é perfeito, pois não há motivo para acessar sua chamada de retorno se a atividade desaparecer. portanto, uma maneira melhor seria manter uma referência a ele e remover seus retornos de chamada assim.
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)
}
}
e, é claro, lida com a limpeza na onPause, para que não atinja o retorno de chamada.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Agora que falamos do óbvio, vamos falar sobre uma opção mais limpa com as corotinas dos dias modernos e o kotlin :). Se você ainda não os está usando, está realmente perdendo.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
ou se você quiser sempre executar uma interface do usuário nesse método, basta:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
É claro que, assim como o PostDelayed, você deve garantir o cancelamento, para que você possa realizar as verificações de atividade após a chamada de atraso ou cancelá-la na onPause, como na outra rota.
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}")
}
}
}
}
// manipular limpeza
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
}
}
Se você colocar a inicialização (UI) na assinatura do método, o trabalho poderá ser atribuído na linha de código de chamada.
para que a moral da história seja segura com suas ações atrasadas, remova seus retornos de chamada ou cancele seus trabalhos e, é claro, confirme que você tem o ciclo de vida certo para tocar nos itens em seu retorno de retorno atrasado. As Coroutines também oferecem ações canceláveis.
Também é importante notar que você geralmente deve lidar com as várias exceções que podem surgir com as corotinas. Por exemplo, um cancelamento, uma exceção, um tempo limite, o que você decidir usar. Aqui está um exemplo mais avançado, se você decidir realmente começar a utilizar corotinas.
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}")
}
}