Janela de atividade vazada que foi adicionada originalmente


1163

O que é esse erro e por que isso acontece?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.ViewRoot.<init>(ViewRoot.java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Dialog.show(Dialog.java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.AsyncTask.execute(AsyncTask.java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP.onCreate(viewP.java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.access$2200(ActivityThread.java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Looper.loop(Looper.java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.main(ActivityThread.java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invoke(Method.java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at dalvik.system.NativeStart.main(Native Method)

6
O outro clássico é quando a orientação muda: stackoverflow.com/questions/1111980/…
rds

Respostas:


1561

Você está tentando mostrar um diálogo depois de sair de uma atividade.

[EDITAR]

Esta questão é uma das principais pesquisas no google para desenvolvedores Android, portanto, adicionando alguns pontos importantes dos comentários, que podem ser mais úteis para futuros investigadores sem aprofundar a conversa sobre os comentários.

Resposta 1 :

Você está tentando mostrar um diálogo depois de sair de uma atividade.

Resposta 2

Esse erro pode ser um pouco enganador em algumas circunstâncias (embora a resposta ainda seja completamente precisa) - ou seja, no meu caso, uma exceção não tratada foi lançada em um AsyncTask, que causou o desligamento da atividade, e um diálogo de progresso aberto causou essa exceção. a exceção 'real' foi um pouco mais cedo no log

Resposta 3

Ligue para dispens () na instância de Diálogo que você criou antes de sair de sua Atividade, por exemplo, em onPause () ou onDestroy ()


2
@ Substituir public void onStop () {if (dialog! = Null) {dialog.dismiss (); dialog = null; }}
Md.Tarikul Islam

14
Mesmo após 8 anos, isso ainda é relevante! Recebi a exceção porque a atividade foi encerrada enquanto tentava exibir meu AlertDialog (portanto, resposta 2). No final, descobri que o aplicativo estava adicionando um objeto "nulo" à cena (não deveria ter acontecido, mas aconteceu), mas não deu uma exceção extra a ele e tudo foi mascarado pelo "vazamento" janela "em vez disso.
Neph 10/09

É possível procurar todas as caixas de diálogo abertas e fechá-las no onStop ()? Eu gero diálogos em um ListView ao clicar nos itens. Não sei como recuperar a referência deles do onStop.
Myoch 8/03/19

1
A resposta 3 é a melhor solução. trabalhou muito para mim. Obrigado kaze, Alex !!
Amit bansode #

dica adicional se você estiver exibindo a caixa de diálogo em um loop garantir a rotina é cancelada após o revestimento atividade
Thecarisma

406

A solução é chamar dismiss()o que Dialogvocê criou viewP.java:183antes de sair Activity, por exemplo, em onPause(). Todos os Windows & Dialogs devem ser fechados antes de sair de um Activity.


3
Então, quando o usuário gira o telefone, todas as caixas de diálogo devem ser descartadas ?? Isso não parece certo.
precisa saber é

@LarsH como você pode ver, minha resposta foi escrita há mais de 7 anos, e isso definitivamente era verdade naquele momento. Eu não trabalho mais com o Android, mas com base no que vejo na documentação , ainda pode ser o caso, mas o Android percorreu um longo caminho desde (introduziu os Fragments apenas para citar um), então é provavelmente mais fácil agora.
molnarm

108

Se você estiver usando AsyncTask, provavelmente essa mensagem de log pode ser enganosa. Se você procurar no seu log, poderá encontrar outro erro, provavelmente um no seu doInBackground()método AsyncTask, que está fazendo sua corrente Activityexplodir e, assim que ela AsyncTaskvoltar ... bem, você sabe o resto. Alguns outros usuários já explicaram isso aqui :-)


22
Às vezes, nesse caso, não consigo ver a exceção real. Para encontrar a exceção real, basta comentar o progressDialog.show () e executar o aplicativo novamente .. agora você vê.
Preso

Oi pessoal! Como mencionado acima por @Stuck, também não consigo ver a exceção real: o que fiz? Eu segui-lo usando pontos de fratura e eu descobri que eu estava usando uma referência de uma classe de aplicações dentro do método doInBackgroundda AsyncTaskclasse, mas sem declará-la no AndroidManifestarquivo usando a propriedade android:namecomo esta: android:name="my.package.MyApplicationClass". Uma boa prática ao usá- AsyncTasklo é sempre lembrar de instanciar seu alerta dentro do método onPreExecutee descartá-lo onPostExecute.
GFPF 23/08/19

66

Acionei esse erro chamando por engano em hide()vez de dismiss()em um AlertDialog.


4
Exatamente o que aconteceu comigo. Além disso, chamar hide () e, em seguida, definir o diálogo como nulo também não é uma alternativa válida.
Lucas Tulio

Eu realmente saberia o problema por trás disso. Mas chamar demitir () me ajudou!
Karoly 29/09

59

Você pode obter essa exceção apenas com um erro simples / burro, ligando acidentalmente finish()depois de exibir um AlertDialog, se você perder uma declaração de chamada de interrupção em uma declaração de chave ...

   @Override
   public void onClick(View v) {
    switch (v.getId()) {
        case R.id.new_button:
            openMyAlertDialog();
            break; <-- If you forget this the finish() method below 
                       will be called while the dialog is showing!
        case R.id.exit_button:
            finish();
            break;
        }
    }

O finish()método fechará o Activity, mas AlertDialogainda está sendo exibido!

Portanto, quando você estiver olhando atentamente para o código, procurando problemas de encadeamento ou codificação complexa, não perca de vista a floresta para as árvores. Às vezes, pode ser algo tão simples e burro quanto uma declaração de pausa ausente. :)


Mais ou menos exatamente o meu problema. Concluído chamado onError após a caixa de diálogo criada, não em onClick para o botão de dispensar.
jbass

46

As respostas para essa pergunta estavam todas corretas, mas um pouco confusas para eu realmente entender o porquê. Depois de brincar por cerca de 2 horas, o motivo desse erro (no meu caso) me atingiu:

Você já sabe, ao ler outras respostas, que o X has leaked window DecorView@d9e6131[]erro possui significa que uma caixa de diálogo foi aberta quando o aplicativo foi fechado. Mas por que?

Pode ser que seu aplicativo tenha travado por algum outro motivo enquanto a caixa de diálogo estava aberta

Isso levou ao fechamento do seu aplicativo devido a algum erro no seu código, que levou a caixa de diálogo a permanecer aberta ao mesmo tempo em que o aplicativo foi fechado devido a outro erro.

Então, olhe através da sua lógica. Resolva o primeiro erro e, em seguida, o segundo erro se resolveráinsira a descrição da imagem aqui

Um erro causa outro, o que causa outro, como DOMINOS!


2
Não posso acreditar que esta tem apenas um upvote .. ou estamos apenas muito ruim em programação hahaha Eu também gostei do seu dominó analogia
user2161301

Resolva o primeiro erro e o segundo erro não ocorrerá . Essa analogia me ajudou.
itabdullah

Isso não está totalmente certo, instâncias como a rotação do telefone também podem causar a rotação da "atividade".
Sreekanth Karumanaghat 30/12/19

36

Esse problema surge ao tentar mostrar uma caixa de diálogo depois que você sai de uma atividade.

Eu apenas resolvi esse problema escrevendo o código a seguir:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( progressDialog!=null && progressDialog.isShowing() ){
        progressDialog.cancel();
    }
}

Basicamente, a partir de qual classe você iniciou progressDialog, substitua o método onDestroy e faça o seguinte. Ele resolveu o problema "A atividade vazou pela janela".


Não é garantido que o onDestroy seja chamado. É melhor colocar esse código no onPause ou noStop #
Amruta-Pani

19

Recentemente, enfrentei o mesmo problema.

A razão por trás desse problema é que a atividade está sendo fechada antes que a caixa de diálogo seja descartada. Existem várias razões para que isso aconteça. Os mencionados nas postagens acima também estão corretos.

Entrei em uma situação, porque no thread eu estava chamando uma função que estava lançando uma exceção. Por causa disso a janela estava sendo fechada e, portanto, a exceção.


16

Ignorar a caixa de diálogo quando a atividade destruir

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}

se pDialog é nulo este irá lançar um erro como você está consultando o estado do diálogo nulo
Jonathan Dunn

1
não, não vai @JonDunn, porque Java não irá processar o segundo booleano se o primeiro é falso
matdev

13

Isso poderia ajudar.

if (! isFinishing()) {

    dialog.show();

    }

2
Entre centenas de respostas semelhantes, não há ninguém mostrando como verificar se o Windows existe. Então você me poupa algum tempo para encontrar o caminho para fazê-lo. Obrigado.
Koliaseg # 21/15

11

Eu tinha a mesma mensagem de erro obscura e não fazia ideia do porquê. Dadas as dicas das respostas anteriores, mudei minhas chamadas não GUI para mDialog.finish () para mDialog.dismiss () e os erros desapareceram. Isso não estava afetando o comportamento do meu widget, mas era desconcertante e poderia muito bem estar sinalizando um importante vazamento de memória.


Percebeu que eu estava fazendo um mDialog.hide () antes da chamada finish (). Mudar para mDialog.dismiss () fez o truque.
maio

11

Eu estava recebendo esses logs no meu aplicativo player de vídeo. Essas mensagens foram lançadas enquanto o player de vídeo estava fechado. Curiosamente, eu costumava obter esses logs uma vez em algumas execuções de maneira aleatória. Além disso, meu aplicativo não envolve em nenhum progressdialog. Finalmente, resolvi esse problema com a implementação abaixo.

@Override
protected void onPause()
{
    Log.v("MediaVideo", "onPause");
    super.onPause();
    this.mVideoView.pause();
    this.mVideoView.setVisibility(View.GONE);
}

@Override
protected void onDestroy()
{
    Log.v("MediaVideo", "onDestroy");
    super.onDestroy();
}

@Override
protected void onResume()
{
    Log.v("MediaVideo", "onResume");
    super.onResume();
    this.mVideoView.resume();
}

Substitua a OnPausechamada com mVideoView.pause()e o conjunto visibilitycomo GONE. Dessa forma, eu poderia resolver o " Activity has leaked window" problema de erro de log.


Eu também estou enfrentando o mesmo problema. eu adicionei essas linhas de código no meu código, mas ele não funcionou e deu o mesmo erro "android.view.WindowLeaked que foi adicionado originalmente" e também não reproduz o vídeo e indica "O vídeo não pode ser reproduzido"
User42590

10

Eu estava tendo o mesmo problema e encontrei esta página e, enquanto minha situação era diferente, liguei finishde um ifbloco antes de definir a caixa de alerta.

Então, simplesmente ligar dismissnão funcionaria (como ainda não foi feito), mas depois de ler a resposta de Alex Volovoy e perceber que era a caixa de alerta que a causava. Tentei adicionar uma declaração de retorno logo após a conclusão dentro desse ifbloco e que corrigiu o problema.

Pensei que depois que você ligasse para terminar, parasse tudo e terminasse ali, mas não. Parece que vai para o final do bloco de código em que está e termina.

Portanto, se você deseja implementar uma situação em que, às vezes, ele termina antes de executar algum código, é necessário colocar uma declaração de retorno logo após o término ou ele continua e continua agindo como se o término tivesse sido chamado no final do bloco de código não onde você o chamou. É por isso que eu estava recebendo todos esses erros estranhos.

private picked(File aDirectory){
     if(aDirectory.length()==0){
        setResult(RESULT_CANCELED, new Intent()); 
        finish(); 
        return;
    }
     AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
     alert
        .setTitle("Question")
        .setMessage("Do you want to open that file?"+aDirectory.getName());
    alert
        .setPositiveButton("OK", okButtonListener)
        .setNegativeButton("Cancel", cancelButtonListener);
    alert.show();
}

Se você não colocar o retorno logo depois que eu chamei de terminar lá, ele funcionará como se você tivesse chamado depois alert.show(); e, portanto, diria que a janela vazou ao terminar logo após você fazer a caixa de diálogo aparecer, mesmo que seja não é o caso, ainda acha que é.

Eu pensei em adicionar isso aqui, pois isso mostra que o comando final agiu de maneira diferente do que eu pensava e acho que há outras pessoas que pensam o mesmo que eu antes de descobrir isso.


7

Esta não é a resposta para a pergunta, mas é relevante para o tópico.

Se a atividade tiver definido um atributo no Manifest

 android:noHistory="true"

depois de executar onPause (), o contexto da atividade é perdido. Portanto, todas as visualizações que usam esse contexto podem gerar esse erro.


Você pode se relacionar qualquer coisa semelhante para progessdialog.show().. e progressdialog.hide()no asynctaskda mesma atividade em vez de onPause()partir activity?? ter um olhar para o meu problema ... stackoverflow.com/questions/39332880/...
Bhuro

1
está funcionando perfeitamente para mim: android: noHistory = "true" #
Shohel Rana 28/11

6

Além de tentar mostrar um alerta, ele também pode ser chamado quando você termina uma instância específica de atividade e tenta iniciar uma nova atividade / serviço ou tenta pará-lo.

Exemplo:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));

6

Geralmente esse problema ocorre devido à caixa de diálogo de progresso: você pode resolver isso usando qualquer um dos métodos a seguir em sua atividade:

 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }

5

Tive o problema de terminar uma atividade quando ainda era mostrado um ProgressDialog.

Então, primeiro oculte a caixa de diálogo e depois termine a atividade.


5

Tente este código:

public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}

progressdialog.dismiss();isso pode criar NullPointerException.
Tpk #

5

Isso pode ocorrer se você tiver um erro na doInBackground()função e tiver esse código.

Tente adicionar a caixa de diálogo, finalmente. Na primeira doInBackground()função de verificação e correção

protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(CreateAccount.this);
     pDialog.setMessage("Creating Product..");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(true);
     pDialog.show();

 }

 protected String doInBackground(String...args) {
     ERROR CAN BE IS HERE
 }

 protected void onPostExecute(String file_url) {
     // dismiss the dialog once done
     pDialog.dismiss();

5

Isso aconteceu comigo quando eu estou usando ProgressDialogno AsyncTask. Na verdade, eu estou usando o hide()método onPostExecute. Com base na resposta de @Alex Volovoy eu preciso usar dismiss()com ProgressDialogpara removê-lo em OnPostExecute e seu feito.

progressDialog.hide(); // Don't use it, it gives error

progressDialog.dismiss(); // Use it

Esta não é realmente a resposta completa. Existem duas maneiras de vazar uma caixa de diálogo. 1) Se você tem um AsyncTaske mostra o Dialog, acontece algo que faz a Activitychamada onPause()(talvez alguma lógica no seu AsyncTask, como um ouvinte, ele vaze. 2) Como mencionado acima, o Dialogque foi criado com ele Activity Contextnunca é demitido e os Activitymovimentos.
Tricknology 21/10

5

O Activity has leaked window that was originally added...erro " " ocorre quando você tenta mostrar um alerta depois que ele Activityé efetivamente finished.

Você tem duas opções AFAIK:

  1. Repense o login do seu alerta: ligue dismiss()para odialog antes de realmente sair do seu atividade.
  2. Coloque o dialogem um thread diferente e execute-o thread(independente da corrente activity).

5

Aqui está uma solução quando você deseja descartar o AlertDialog, mas não deseja manter uma referência a ele dentro da atividade.

solução requer que você tenha androidx.lifecycle dependência no seu projeto (acredito que no momento do comentário é um requisito comum)

isso permite delegar a dispensa da caixa de diálogo a um objeto externo (observador), e você não precisa mais se preocupar com isso, porque ela é cancelada automaticamente quando a atividade morre. (aqui está a prova: https://github.com/googlecodelabs/android-lifecycles/issues/5 ).

portanto, o observador mantém a referência ao diálogo e a atividade mantém a referência ao observador. quando "onPause" acontece - o observador rejeita a caixa de diálogo e quando "onDestroy" acontece - a atividade remove o observador, portanto não ocorre vazamento (bem, pelo menos não vejo mais erro no logcat)

// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        dialog?.dismiss()
        dialog = null
    }
}
// activity code
private fun showDialog() {
        if( isDestroyed || isFinishing ) return
        val dialog = AlertDialog
            .Builder(this, R.style.DialogTheme)
            // dialog setup skipped
            .create()
        lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
        dialog.show()
}

4

As exceções que vazaram na janela têm dois motivos:

1) mostrando a caixa de diálogo quando o Contexto da Atividade não existe, para resolver isso, você deve mostrar a caixa de diálogo apenas para ter certeza de que a Atividade existe:

if(getActivity()!= null && !getActivity().isFinishing()){
        Dialog.show();
}

2) não descartar o diálogo adequadamente, para resolver, use este código:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}

4

Você deve criar um Progressdialogobjeto no onPreExecutemétodo de AsyncTaske deve dismissfazê-lo no onPostExecutemétodo


4

A melhor solução é apenas adicionar uma caixa de diálogo na tentativa de capturar e descartar a caixa de diálogo quando ocorrer uma exceção

Basta usar o código abaixo

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }

3
? Não é de diálogo será nulo após chamada terminar, eu acho que dialog.dismiss()vai produzir erro também
Ashu Kumar

3

No meu caso, o motivo foi que esqueci de incluir uma permissão no arquivo de manifesto do Android.

Como eu descobri? Bem, assim como o @Bobby diz em um comentário abaixo da resposta aceita, basta ir até seus logs e você verá o primeiro motivo ou evento que realmente gerou a exceção. Aparentemente, a mensagem "A atividade vazou na janela que foi adicionada originalmente" é apenas uma exceção que resultou de qualquer que seja a primeira exceção.


3

Tente o código abaixo, ele funcionará sempre que você descartar o diálogo de progresso e verificar se a instância está disponível ou não.

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

2

A melhor solução é colocar isso antes de mostrar progressbarouprogressDialog

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}

Isso não funciona para mim. Eu tenho Dialog.show () após a resposta da chamada HTTP e, enquanto isso, eu giro a tela A atividade é desanexada, mas parece ter isShown == true antes de Dialog.show () e, em seguida, o Dialog falha apesar dessa verificação
Michał Ziobro 12/09

1

Apenas verifique se sua atividade não está sendo fechada inesperadamente devido a algumas exceções levantadas em algum lugar do seu código. Geralmente isso acontece na tarefa assíncrona quando a atividade enfrenta o fechamento forçado no método doinBackground e, em seguida, a asynctask retorna ao método onPostexecute.


1

Eu tenho outra solução para isso e gostaria de saber se parece válido para você: em vez de dispensar o onDestroy, que parece ser a solução líder, estou estendendo o ProgressDialog ...

public class MyProgressDialog extends ProgressDialog {

  private boolean isDismissed;

  public MyProgressDialog(Context context) {
    super(context);
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    dismiss();
  }

  @Override
  public void dismiss() {
    if (isDismissed) {
      return;
    }
    try {
      super.dismiss();
    } catch (IllegalArgumentException e) {
      // ignore
    }
    isDismissed = true;
  }

Isso é preferível, AFAIC, porque você não precisa manter o diálogo de progresso como membro, apenas dispare (mostre) e esqueça

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.