Eu tenho uma atividade que inicia o AsyncTask e mostra o diálogo de progresso pela duração da operação. A atividade é declarada NÃO ser recriada por rotação ou slide do teclado.
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
Depois que a tarefa é concluída, eu encerro a caixa de diálogo, mas em alguns telefones (estrutura: 1.5, 1.6) esse erro é gerado:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201)
at android.view.Window$LocalWindowManager.removeView(Window.java:400)
at android.app.Dialog.dismissDialog(Dialog.java:268)
at android.app.Dialog.access$000(Dialog.java:69)
at android.app.Dialog$1.run(Dialog.java:103)
at android.app.Dialog.dismiss(Dialog.java:252)
at xxx.onPostExecute(xxx$1.java:xxx)
Meu código é:
final Dialog dialog = new AlertDialog.Builder(context)
.setTitle("Processing...")
.setCancelable(true)
.create();
final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() {
@Override
protected MyResult doInBackground(MyParams... params) {
// Long operation goes here
}
@Override
protected void onPostExecute(MyResult result) {
dialog.dismiss();
onCompletion(result);
}
};
task.execute(...);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface arg0) {
task.cancel(false);
}
});
dialog.show();
Pelo que li ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html ) e visto nas fontes do Android, parece a única situação possível para obter isso exceção é quando a atividade foi destruída. Mas, como mencionei, proíbo a recreação de atividades para eventos básicos.
Portanto, todas as sugestões são muito apreciadas.
Respostas:
Às vezes, eu também recebo esse erro quando descartar a caixa de diálogo e concluir a atividade do método onPostExecute. Acho que às vezes a atividade termina antes que o diálogo seja encerrado com êxito.
Solução simples e eficaz que funciona para mim
fonte
Aqui está minha solução "à prova de balas", que é a compilação de todas as boas respostas que encontrei sobre esse tópico (graças a @Damjan e @Kachi). Aqui a exceção é engolida apenas se todas as outras formas de detecção não tiverem êxito. No meu caso, preciso fechar a caixa de diálogo automaticamente e esta é a única maneira de proteger o aplicativo contra falhas. Espero que ajude você! Por favor, vote e deixe comentários se você tiver comentários ou uma solução melhor. Obrigado!
fonte
dialog = null
não tem nenhum efeito. EStatusEventDialog
deve ler apenasDialog
.isDestroyed()
não esteja disponível, mas por motivos práticos não seria o mesmo usar sempre o try / catch sempre?Eu posso ter uma solução alternativa.
Estava com o mesmo problema, onde estou carregando muitos itens (via sistema de arquivos) em um
ListView
via anAsyncTask
. Teve oonPreExecute()
acionamento de umProgressDialog
e, em seguida, ambosonPostExecute()
eonCancelled()
(chamado quando a tarefa é cancelada explicitamente viaAsyncTask.cancel()
) fechando-a via.cancel()
.Obteve o mesmo erro "java.lang.IllegalArgumentException: exibição não anexada ao gerenciador de janelas" quando estava matando a caixa de diálogo no
onCancelled()
método doAsyncTask
(eu já tinha visto isso no excelente aplicativo Shelves ).A solução alternativa foi criar um campo público no
AsyncTask
que contém oProgressDialog
:Então,
onDestroy()
quando cancelo o meuAsyncTask
, também posso matar a caixa de diálogo associada via:A chamada
AsyncTask.cancel()
DOES é acionadaonCancelled()
noAsyncTask
, mas, por algum motivo, quando o método é chamado, a Visualização já foi destruída e, portanto, o cancelamento da caixa de diálogo está falhando.fonte
Aqui está a solução correta para resolver esse problema:
Em vez de capturar todas as exceções às cegas, esta solução aborda a raiz do problema: tentar reduzir o tamanho de um diálogo quando a atividade usada para inicializar o diálogo já tiver sido concluída. Trabalhando no meu Nexus 4 executando o KitKat, mas deve funcionar para todas as versões do Android.
fonte
isDestroyed
requer API 17+eu concordo com uma opinião de 'Damjan'.
se você usar muitas caixas de diálogo, feche todas as caixas de diálogo em onDestroy () ou onStop ().
poderá reduzir a frequência 'java.lang.IllegalArgumentException: ocorre a exceção da exibição não anexada ao gerenciador de janelas'.
mas pouco excede ...
para tornar mais claro, você evita exibir qualquer caixa de diálogo após a ligação de OnDestroy.
Eu não uso como abaixo. mas está claro.
boa sorte!
fonte
Usa isto.
fonte
if
em casos como este, o&&
operador do Java tem uma avaliação lenta (também chamada de curto-circuito), o que significa que o segundo operando não é avaliado se o primeiro avaliarfalse
(o que significa o resultado de o&&
será semprefalse
de qualquer maneira, portanto avaliação "preguiçoso"). Da mesma forma||
, não avaliará seu segundo operando se o primeiro avaliartrue
. Nota: os operadores&
e|
não têm esse comportamento e, portanto, sempre avaliam os dois operandos.Eu tive o mesmo problema, você pode resolvê-lo:
fonte
Acho que seu código está correto, diferente da outra resposta sugerida. onPostExecute será executado no thread da interface do usuário. Esse é o ponto principal do AsyncTask - você não precisa se preocupar em chamar runOnUiThread ou lidar com manipuladores. Além disso, de acordo com os documentos, pode-se chamar de forma segura () a partir de qualquer encadeamento (sem ter certeza de que eles fizeram disso a exceção).
Talvez seja um problema de tempo em que dialog.dismiss () está sendo chamado depois que a atividade não é mais exibida?
Que tal testar o que acontece se você comentar o setOnCancelListener e sair da atividade enquanto a tarefa em segundo plano estiver em execução? Em seguida, seu onPostExecute tentará descartar uma caixa de diálogo já descartada. Se o aplicativo travar, você provavelmente pode apenas verificar se a caixa de diálogo está aberta antes de descartá-la.
Estou tendo exatamente o mesmo problema, então vou testá-lo em código.
fonte
alex
Eu posso estar errado aqui, mas suspeito que vários telefones "em estado selvagem" têm um bug que os leva a mudar de orientação em aplicativos marcados como estaticamente orientados. Isso acontece bastante no meu telefone pessoal e em muitos dos telefones de teste que nosso grupo usa (incluindo droid, n1, g1, hero). Normalmente, um aplicativo marcado como estaticamente orientado (talvez verticalmente) se expõe por um segundo ou dois usando uma orientação horizontal e depois retorna imediatamente. O resultado final é que, mesmo que você não queira que seu aplicativo mude de orientação, você deve estar preparado para isso. Não sei em que condições exatas esse comportamento pode ser reproduzido, não sei se é específico para uma versão do Android. Tudo o que sei é que já vi isso acontecer muitas vezes :(
Eu recomendaria usar a solução fornecida no link que você postou, que sugere substituir o método Activity onCreateDialog e permitir que o sistema operacional Android gerencie o ciclo de vida dos seus Diálogos. Parece-me que, embora você não queira que sua atividade mude de orientação, ela está mudando de orientação em algum lugar. Você pode tentar rastrear um método que sempre impeça a troca de orientação, mas estou tentando lhe dizer que pessoalmente não acredito que exista uma maneira infalível de funcionar em todos os telefones Android atuais do mercado.
fonte
O que funcionou para mim na maioria das vezes é verificar se a Atividade não está terminando.
fonte
Só tenho o mesmo problema. Correção para API nível 13 ou mais alto.
Dos documentos do Android:
Então, eu mudei meu manifesto para isso:
E agora funciona bem. A atividade não é recriada quando eu giro o telefone, a caixa de diálogo de progresso e a exibição permanecem as mesmas. Nenhum erro para mim.
fonte
Antes de tudo, faça o tratamento de erros sempre que estiver tentando descartar a caixa de diálogo.
Se isso não corrigir, descarte-o no método onStop () da atividade.
fonte
Eu tive o mesmo problema ao usar um botão para sincronizar uma lista do servidor: 1) clico no botão 2) Uma caixa de diálogo de progresso é exibida durante o download da lista do servidor 3) mudo o dispositivo para outra orientação 4) java.lang .IllegalArgumentException: exibição não anexada ao gerenciador de janelas em postExecute () do AsyncTask durante progress.dismiss ().
Ao tentar a correção, percebi que, mesmo que o problema não ocorra, minha lista não estava mostrando todos os itens.
Imaginei que o que eu queria era que o AsyncTask terminasse (e descartasse a caixa de diálogo) antes que a atividade fosse destruída, então fiz do objeto asynctask um atributo e substitui o método onDestroy ().
Se o assíncrono demorar muito tempo, talvez o usuário sinta que o dispositivo está lento, mas acho que esse é o preço que ele paga por tentar mudar a orientação do dispositivo enquanto a caixa de diálogo de progresso é exibida. E mesmo que demore algum tempo, o aplicativo não falha.
fonte
fonte
Abaixo, o código funciona para você, funciona perfeitamente para mim:
Não defina sua visão globalmente se você a chamar do serviço em segundo plano.
fonte