Citando a documentação para AsyncTask encontrada aqui , diz:
O AsyncTasks deve ser usado idealmente para operações curtas (alguns segundos no máximo). Se você precisa manter os threads em execução por longos períodos, é altamente recomendável usar as várias APIs fornecidas pelo pacote java.util.concurrent, como Executor, ThreadPoolExecutor e FutureTask.
Agora surge a minha pergunta: por quê? A doInBackground()
função é executada fora do thread da interface do usuário, então que mal há em ter uma operação longa aqui?
android
android-asynctask
user1730789
fonte
fonte
doInBackground
função de longa duração congela a tela se uma barra de progresso não for usada.Respostas:
É uma pergunta muito boa, um programador Android leva tempo para entender completamente o problema. Na verdade, AsyncTask tem dois problemas principais relacionados:
Dentro do aplicativo RoboSpice Motivations ( disponível no Google Play ), respondemos a essa pergunta em detalhes. Ele dará uma visão aprofundada de AsyncTasks, Loaders, seus recursos e desvantagens e também apresentará uma solução alternativa para solicitações de rede: RoboSpice. As solicitações de rede são um requisito comum no Android e são, por natureza, operações de longa duração. Aqui está um trecho do aplicativo:
O ciclo de vida AsyncTask e Activity
AsyncTasks não seguem o ciclo de vida das instâncias de Activity. Se você iniciar uma AsyncTask dentro de uma Activity e girar o dispositivo, a Activity será destruída e uma nova instância será criada. Mas o AsyncTask não morrerá. Ele continuará vivendo até que seja concluído.
E quando for concluído, o AsyncTask não atualizará a IU da nova Activity. Na verdade, ele atualiza a instância anterior da atividade que não é mais exibida. Isso pode levar a uma Exceção do tipo java.lang.IllegalArgumentException: Visualização não anexada ao gerenciador de janelas se você usar, por exemplo, findViewById para recuperar uma visualização dentro da Atividade.
Problema de vazamento de memória
É muito conveniente criar AsyncTasks como classes internas de suas atividades. Como o AsyncTask precisará manipular as visualizações da Activity quando a tarefa for concluída ou em andamento, o uso de uma classe interna da Activity parece conveniente: as classes internas podem acessar diretamente qualquer campo da classe externa.
No entanto, isso significa que a classe interna manterá uma referência invisível em sua instância de classe externa: a Activity.
No longo prazo, isso produz um vazamento de memória: se a AsyncTask durar muito, ela manterá a atividade "viva", enquanto o Android gostaria de eliminá-la, pois não pode mais ser exibida. A atividade não pode ser coletada como lixo e esse é um mecanismo central para o Android preservar os recursos do dispositivo.
É realmente uma péssima ideia usar AsyncTasks para operações de longa duração. No entanto, eles são bons para aqueles de curta duração, como atualizar uma Visualização após 1 ou 2 segundos.
Eu encorajo você a baixar o aplicativo RoboSpice Motivations , ele realmente explica isso em profundidade e fornece exemplos e demonstrações das diferentes maneiras de fazer algumas operações em segundo plano.
fonte
Porque
AsyncTask
, por padrão, usa um pool de threads que você não criou . Nunca amarre recursos de um pool que você não criou, pois você não sabe quais são os requisitos desse pool. E nunca bloqueie recursos de um pool que você não criou, se a documentação desse pool disser que não, como é o caso aqui.Em particular, começando com o Android 3.2, o pool de threads usado por
AsyncTask
padrão (para aplicativos comandroid:targetSdkVersion
definido como 13 ou superior) tem apenas um thread nele - se você amarrar este thread indefinidamente, nenhuma de suas outras tarefas será executada.fonte
Service
, basta usar aThread
ou aThreadPoolExecutor
.TimerTask
é do Java padrão, não do Android.TimerTask
foi amplamente abandonado em favor deScheduledExecutorService
(o que, apesar do nome, faz parte do Java padrão). Nenhum deles está vinculado ao Android e, portanto, você ainda precisa de um serviço se espera que esses itens sejam executados em segundo plano. E, você realmente deve considerarAlarmManager
, a partir do Android, então você não precisa de um serviço rondando, apenas assistindo o tique-taque do relógio.As tarefas Aysnc são threads especializados que ainda devem ser usados com a GUI de seus aplicativos, mas mantendo as tarefas pesadas de recursos do thread da interface do usuário. Então, quando coisas como atualizar listas, alterar suas visualizações etc. exigem que você faça algumas operações de busca ou atualização, você deve usar tarefas assíncronas para que possa manter essas operações fora do thread da IU, mas observe que essas operações ainda estão conectadas à IU de alguma forma .
Para tarefas de execução mais longa, que não requerem atualização da IU, você pode usar os serviços, porque eles podem viver mesmo sem uma IU.
Portanto, para tarefas curtas, use tarefas assíncronas porque elas podem ser eliminadas pelo sistema operacional depois que sua atividade de desova morrer (geralmente não morrerá no meio da operação, mas concluirá sua tarefa). E para tarefas longas e repetitivas, use os serviços.
para mais informações, veja os tópicos:
AsyncTask por mais de alguns segundos?
e
AsyncTask não para mesmo quando a atividade é destruída
fonte
O problema com AsyncTask é que, se for definida como uma classe interna não estática da atividade, terá uma referência à atividade. No cenário em que a atividade do contêiner da tarefa assíncrona termina, mas o trabalho em segundo plano em AsyncTask continua, o objeto de atividade não será coletado como lixo porque há uma referência a ele, isso causa o vazamento de memória.
A solução para corrigir isso é definir a tarefa assíncrona como uma classe interna estática de atividade e usar uma referência fraca ao contexto.
Mesmo assim, é uma boa ideia usá-lo para tarefas simples e rápidas em segundo plano. Para desenvolver um aplicativo com código limpo, é melhor usar RxJava para executar tarefas complexas em segundo plano e atualizar a IU com os resultados dela.
fonte