Eu li muito sobre como salvar meu estado de instância ou como lidar com minha atividade sendo destruída durante a rotação da tela.
Parece haver muitas possibilidades, mas ainda não descobri qual funciona melhor para recuperar os resultados de uma AsyncTask.
Eu tenho alguns AsyncTasks que são simplesmente iniciados novamente e chamam o isFinishing()
método da atividade e se a atividade estiver terminando eles não atualizarão nada.
O problema é que tenho uma tarefa que faz uma solicitação a um serviço da web que pode falhar ou ter sucesso e reiniciar a tarefa resultaria em perda financeira para o usuário.
Como você resolveria isso? Quais são as vantagens ou desvantagens das soluções possíveis?
setRetainInstance(true)
realmente é útil.Respostas:
Minha primeira sugestão seria ter certeza de que você realmente precisa que sua atividade seja redefinida em uma rotação de tela (o comportamento padrão). Sempre que tive problemas com a rotação, adicionei esse atributo à minha
<activity>
tag no AndroidManifest.xml e estava tudo bem.Parece estranho, mas o que ele faz é passar para o seu
onConfigurationChanged()
método, se você não fornecer um ele não faz nada além de medir novamente o layout, o que parece ser uma forma perfeitamente adequada de lidar com o giro na maioria das vezes .fonte
Você pode verificar como eu lido
AsyncTask
com mudanças de orientação em code.google.com/p/shelves . Existem várias maneiras de fazer isso, a que escolhi neste aplicativo é cancelar qualquer tarefa em execução no momento, salvar seu estado e iniciar uma nova com o estado salvo quando a novaActivity
for criada. É fácil de fazer, funciona bem e, como bônus, cuida de interromper suas tarefas quando o usuário sai do aplicativo.Você também pode usar
onRetainNonConfigurationInstance()
para passar seuAsyncTask
para o novoActivity
(noActivity
entanto, tome cuidado para não vazar o anterior dessa forma.)fonte
Essa é a pergunta mais interessante que já vi em relação ao Android !!! Na verdade, já estou procurando a solução nos últimos meses. Ainda não resolvi.
Tenha cuidado, simplesmente substituindo o
coisas não são suficientes.
Considere o caso em que o usuário recebe uma chamada telefônica enquanto o AsyncTask está em execução. Sua solicitação já está sendo processada pelo servidor, portanto, AsyncTask está aguardando resposta. Nesse momento, seu aplicativo entra em segundo plano, pois o aplicativo Telefone acaba de entrar em primeiro plano. OS pode matar sua atividade, pois está em segundo plano.
fonte
Por que você não sempre mantém uma referência à AsyncTask atual no Singleton fornecido pelo Android?
Sempre que uma tarefa é iniciada, no PreExecute ou no construtor, você define:
((Application) getApplication()).setCurrentTask(asyncTask);
Sempre que terminar, você o define como nulo.
Dessa forma, você sempre tem uma referência que permite fazer algo como onCreate ou onResume conforme apropriado para sua lógica específica:
this.asyncTaskReference = ((Application) getApplication()).getCurrentTask();
Se for null, você sabe que não há nenhum em execução no momento!
:-)
fonte
Application
A instância tem seu próprio ciclo de vida - ela também pode ser eliminada pelo sistema operacional, portanto, essa solução pode causar um bug difícil de reproduzir.A maneira mais adequada de fazer isso é usar um fragmento para reter a instância da tarefa assíncrona, em rotações.
Aqui está um link para um exemplo muito simples, tornando mais fácil acompanhar a integração dessa técnica em seus aplicativos.
https://gist.github.com/daichan4649/2480065
fonte
Em
Pro android 4
. autor sugeriu uma maneira legal, que você deveria usarweak reference
.Nota de referência fraca
fonte
No meu ponto de vista, é melhor armazenar asynctask
onRetainNonConfigurationInstance
desacoplando-o do objeto Activity atual e ligando-o a um novo objeto Activity após a mudança de orientação. Aqui encontrei um exemplo muito bom de como trabalhar com AsyncTask e ProgressDialog.fonte
Android: processamento em segundo plano / operação assíncrona com alteração de configuração
Para manter os estados de operação assíncrona durante o processo em segundo plano: você pode obter a ajuda de fragmentos.
Veja as seguintes etapas:
Etapa 1: crie um fragmento sem cabeçalho, digamos, tarefa em segundo plano e adicione uma classe de tarefa assíncrona privada com ele.
Etapa 2 (etapa opcional): se você deseja colocar um cursor de carregamento no topo de sua atividade, use o código abaixo:
Etapa 3: em sua atividade principal, implemente a interface BackgroundTaskCallbacks definida na etapa 1
}
fonte
Uma coisa a se considerar é se o resultado da AsyncTask deve estar disponível apenas para a atividade que iniciou a tarefa. Se sim, então a resposta de Romain Guy é a melhor. Se ele deve estar disponível para outras atividades do seu aplicativo,
onPostExecute
você pode usá-loLocalBroadcastManager
.Você também precisará se certificar de que a atividade lida corretamente com a situação quando a transmissão é enviada enquanto a atividade está pausada.
fonte
Dê uma olhada neste post . Este Post envolve AsyncTask realizando uma operação de longa duração e vazamento de memória quando a rotação da tela ocorre em um aplicativo de amostra. O aplicativo de amostra está disponível no forge de origem
fonte
Minha solução.
No meu caso, tenho uma cadeia de AsyncTasks com o mesmo contexto. A atividade teve acesso apenas ao primeiro. Para cancelar qualquer tarefa em execução, fiz o seguinte:
Tarefa
doInBackground()
:Atividade
onStop()
ouonPause()
:fonte
fonte
você também pode adicionar android: configChanges = "keyboardHidden |idance | screenSize"
ao seu exemplo manifesto, espero que ajude
fonte