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)
Pentium10
fonte
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 ()

Alex Volovoy
fonte
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.

molnarm
fonte
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 :-)

ggomeze
fonte
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.

Mark Phillip
fonte
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. :)

Adrian Romanelli
fonte
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!

Ruchir Baronia
fonte
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".

Shoaib Ahmed
fonte
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.

Tushar
fonte
16

Ignorar a caixa de diálogo quando a atividade destruir

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}
Muhammad Aamir Ali
fonte
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();

    }
arenoso
fonte
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.

Melinda Green
fonte
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.

InvisiblePoint
fonte
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.

Kit Ramos
fonte
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.

Assassino
fonte
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));
Kulbhushan Chaskar
fonte
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();
                }
            }
Bapusaheb Shinde
fonte
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.

LeonS
fonte
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
    }

}
tinku
fonte
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();
NickUnuchek
fonte
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
SANAT
fonte
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).
Kyle Clegg
fonte
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()
}
dmz9
fonte
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();
}
}
Xerez
fonte
4

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

ammad
fonte
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();
    }
Ness Tyagi
fonte
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.

Matthew Quiros
fonte
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();
    }
Desenvolvedor
fonte
2

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

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

  //Show Your Progress Dialog

}
Ali Akram
fonte
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.

Manas Ranjan
fonte
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

Kalisky
fonte