Estou usando o ACRA para relatar falhas no aplicativo. Eu estava recebendo uma View not attached to window manager
mensagem de erro e pensei que tinha corrigido, envolvendo a pDialog.dismiss();
instrução if:
if (pDialog!=null)
{
if (pDialog.isShowing())
{
pDialog.dismiss();
}
}
Reduziu a quantidade de View not attached to window manager
falhas que recebo, mas ainda estou recebendo algumas e não tenho certeza de como resolvê-la.
Mensagem de erro:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:425)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:327)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:83)
at android.app.Dialog.dismissDialog(Dialog.java:330)
at android.app.Dialog.dismiss(Dialog.java:312)
at com.package.class$LoadAllProducts.onPostExecute(class.java:624)
at com.package.class$LoadAllProducts.onPostExecute(class.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Fragmento de código:
class LoadAllProducts extends AsyncTask<String, String, String>
{
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(CLASS.this);
pDialog.setMessage("Loading. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args)
{
// Building Parameters
doMoreStuff("internet");
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url)
{
// dismiss the dialog after getting all products
if (pDialog!=null)
{
if (pDialog.isShowing())
{
pDialog.dismiss(); //This is line 624!
}
}
something(note);
}
}
Manifesto:
<activity
android:name="pagename.CLASS"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
android:label="@string/name" >
</activity>
O que estou perdendo para impedir que esse acidente aconteça?
AsyncTask
é declarado dentroActivity
ouFragment
?Respostas:
Como reproduzir o bug:
Settings -> Developer Options -> Don't keep Activities
.AsyncTask
estiver em execução e emProgressDialog
exibição.O sistema operacional Android destruirá uma atividade assim que estiver oculta. Quando
onPostExecute
é chamado, o estadoActivity
estará em "acabamento" eProgressDialog
não será anexadoActivity
.Como corrigi-lo:
onPostExecute
método.ProgressDialog
inonDestroy
. Caso contrário, aandroid.view.WindowLeaked
exceção será lançada. Essa exceção geralmente vem de diálogos que ainda estão ativos quando a atividade está terminando.Experimente este código fixo:
fonte
isDestroyed()
ao longoisFinishing()
de todas as APIs para esta finalidade específica?isFinishing()
não é garantidotrue
que a atividade seja destruída pelo sistema, consulte a documentação em Atividades .// or call isFinishing() if min sdk version < 17
, ele se depara com a mesma exceção. Então, precisamos de uma solução diferente do que esta resposta para aplicativos que funcionam em API <17.myActivityWeakReference.get() != null && !myActivityWeakReference.get().isFinishing()
Questão poderia ser que o
Activity
tenham sidofinished
ou emprogress of finishing
.Adicione uma verificação
isFinishing
e descartar a caixa de diálogo apenas quando esta forfalse
isFinishing: verifique se esta atividade está em processo de conclusão, porque você a chamou
finish
ou alguém solicitou a conclusão.fonte
Para
Dialog
criado em aFragment
, eu uso o seguinte código:Eu uso esse padrão para lidar com o caso em que um
Fragment
pode ser desanexado doActivity
.fonte
Veja como o Código está funcionando aqui:
Depois de chamar a tarefa assíncrona, a tarefa assíncrona é executada em segundo plano. isso é desejável. Agora, esta tarefa assíncrona tem uma caixa de diálogo de progresso anexada à atividade, se você perguntar como ver o código:
Você está passando o
Class.this
contexto como para o argumento. Portanto, a caixa de diálogo Progresso ainda está anexada à atividade.Agora considere o cenário: Se tentarmos concluir a atividade usando o método finish (), enquanto a tarefa assíncrona estiver em andamento, é o ponto em que você está tentando acessar o Recurso anexado à atividade, ou seja,
progress bar
quando a atividade não está mais há.Daí você obtém:
Solução para isso:
1) Verifique se a caixa de diálogo foi descartada ou cancelada antes do término da atividade.
2) Conclua a atividade, somente depois que a caixa de diálogo for descartada, ou seja, a tarefa assíncrona terminou.
fonte
Activity
; O Android pode terminar a qualquer momento. Então, o nº 2 não faz sentido.Com base na resposta @erakitin, mas também compatível com as versões do Android <nível API 17. O Sadly Activity.isDestroyed () só é suportado desde o nível 17 da API. Portanto, se você estiver direcionando para um nível API mais antigo como eu, será necessário verifique você mesmo. Não tenho a
View not attached to window manager
exceção depois disso.Código de exemplo
fonte
consulte isso .
fonte
Substituir onConfigurationChanged e descartar a caixa de diálogo de progresso. Se a caixa de diálogo de progresso for criada em modo retrato e for descartada em paisagem, ocorrerá o erro Ver não anexado ao gerenciador de janelas.
Pare também a barra de progresso e a tarefa assíncrona nos métodos onPause (), onBackPressed e onDestroy.
fonte
Substituir na destruição da atividade e dispensar seu diálogo e torná-lo nulo
fonte
Em primeiro lugar, o motivo da falha é o índice do decorView é -1, podemos conhecê-lo a partir do código fonte do Android, existe um trecho de código:
para que possamos seguir a resolução, apenas julgue o índice do decorView, se mais de 0 continuar ou simplesmente retornar e desistir, descubra o código da seguinte maneira:
fonte
Substitua o
dismiss()
método como este:Para reproduzir o problema, basta concluir a atividade antes de fechar a caixa de diálogo.
fonte
melhor solução. Verificar o primeiro contexto é o contexto da atividade ou o contexto do aplicativo se o contexto da atividade somente verificar a atividade concluída ou não chamar
dialog.show()
oudialog.dismiss();
Se você deseja adicionar mais verificações, adicione
dialog.isShowing()
oudialog !-null
use a&&
condição.fonte
Esse problema ocorre porque sua atividade é concluída antes que a função de dispensa seja chamada. Manipule a exceção e verifique seu log do ADB pelo motivo exato.
fonte
Eu tenho uma maneira de reproduzir essa exceção.
Eu uso 2
AsyncTask
. Um faz tarefas longas e outro faz tarefas curtas. Após a conclusão da tarefa curta, liguefinish()
. Quando uma tarefa longa é concluída e é chamadaDialog.dismiss()
, ela falha.Aqui está o meu código de exemplo:
Você pode tentar isso e descobrir qual é a melhor maneira de corrigir esse problema. No meu estudo, há pelo menos quatro maneiras de corrigi-lo:
isFinishing()
para verificar o estado da atividadeAsyncTask.cancel(false)
noonDestroy()
. Isso impedirá que o asynctask seja executado,onPostExecute()
mas é executadoonCancelled()
.Nota:
onPostExecute()
ainda será executado mesmo que você ligueAsyncTask.cancel(false)
no sistema operacional Android mais antigo, como o Android 2.XXVocê pode escolher o melhor para você.
fonte
Pode ser que você inicialize o pDialog globalmente, remova-o e inicialize sua exibição ou caixa de diálogo localmente. Eu tenho o mesmo problema, eu fiz isso e meu problema foi resolvido. Espero que funcione para você.
fonte
também descartamos nosso diálogo sobre
onPause
método ouonDestroy
métodofonte