Como limpar AsyncTasks da memória após execução?

Estou desenvolvendo um APP comercial, neste preciso carregar todos os clientes do estabelecimento, então eu faço uma requisição solicitando cada cliente, pois preciso mandar o Id deste na URL da requisição, até ai tudo bem, o problema é que quando faço por exemplo, requisição de 150 clientes funciona, isto resulta em 150 new AsyncTask().execute();.

Em um próximo cenário preciso requisitar 700 clientes, ou seja, 700 new AsyncTask().execute(); então preciso limpar da memória os que já foram concluídos, ja tentei
new AsyncTask().executeOnExecutor(Executors.newSingleThreadExecutor()); não tive sucesso.

  • Como estou chamando novamente o Async atualmente:

Eu tenho um ArrayList que contem os ID dos clientes que eu necessito ‘pegar’ ,(tenho um EndPoint que me retorna os IDs de Clientes que posso ‘pegar’), então a cada sincronização mando a posição 0 desse array como parâmetro, então vai o ID do cliente ao final removo a posição 0 e faço uma verificação se ainda exite cliente sem sincronizar.
Código do OnPostExecute():

clientesAguardandoSincronizar.remove(0);
mAsyncCliente = null;
if(clientesAguardandoSincronizar.size()>0){
     //Executa novamente o Async de Clientes para trazer um a um.
     mAsyncCliente = new AsyncCliente(context).execute();
}else{
     //Executa proxima AsyncTask.
}

Pq dentro do AsyncTask vc não faz um loop que faz essas requisições todas ao invés de fazer 700 asynctasks. Faz mais sentido vc ter um serviço assincrono que faz um monte de requisição do que um monte de serviço que faz uma requisição. Vc está criando um monte de processos assíncronos que fazem a mesma coisa. Se eu não me engano o S.O não permite que vc execute multiplos asynctask seguidos.

java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)

A mesma instancia de asynctask não pode ser executada, a não ser que vc cancele-a e execute novamente.

Em java vc não limpa um objeto da memória (ao menos vc não deveria). Quem faz isso é o Garbbage collector que sabe quando uma referência a um objeto não é mais utilizada.

1 curtida

Oque acontece hoje é que no OnPostExecute eu verifico o retorno do servidor. No caso de de Erros e Code 401 por exemplo. E eu sempre faço um new AsyncTask() quando vou executar ela novamente. Mas vou tentar fazer isto.

Guarda os que deram erro numa fila e tenta de novo. Da uma estuda em AlarmManager, com ele vc pode criar uma Tarefa que executa a cada intervalo de tempo as requisições que não deram certo, quando a fila estiver vazia vc pode matar o alarmManager

1 curtida

@chrislucas Muito obrigado, eu consegui resolver meu problema. Aconteceu isso porque estava usando Volley e cada requisição ele gerada uma Thread e deixava ela na memória. Usei HTTPRequest e fiz todas as requisições da mesma AsyncTask, e funcionou certinho. Sei que o HTTP do Apahce está obsoleto então vou mudar para OkHttp.

Ai sim. Quando puder de uma olhada no Retrofit, é uma library bem legal para fazer requisições, síncronas e assíncronas.

http://square.github.io/retrofit/.

É da mesma empresa que fez a OkHttp.

Outra biblioteca que encapsula requisições http é essa, https://github.com/kevinsawicki/http-request. Tenho projetos que ainda não mudei para retrofit que uso essa library.

1 curtida

@chrislucas E conheço Retrofit mas não gosto da ideia de Criar Interfaces para Amarrar as consultas como ele trabalha, porque como estou usando API de terceiro, as vezes ocorre muitas alterações nos endereços e nos parâmetros ai acho mais fácil quando consigo apenas mandar toda a URL na requisição como funciona o Volley e o HTTP mas acho que terei que me entregar ao Retrofit nos próximos projetos. Rsrsrs Mas vou olhar esta outra ai.

Ah, esqueci de dizer também que nesta API preciso enviar o Token no Header de cada requisição e não descobri como faz isso com Retrofit.

Mas até onde eu li, dá pra programar meios de o retrofit receber a url inteira na interface… https://stackoverflow.com/questions/32559333/retrofit-2-dynamic-url