Aktywność wyciekła okno, które zostało pierwotnie dodane

1160

Co to za błąd i dlaczego się zdarza?

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
źródło
6
Drugim klasykiem jest zmiana orientacji: stackoverflow.com/questions/1111980/…
rds

Odpowiedzi:

1559

Próbujesz wyświetlić okno dialogowe po wyjściu z działania.

[EDYTOWAĆ]

To pytanie jest jednym z najlepszych wyników wyszukiwania w Google dla programistów Androida, dlatego dodanie kilku ważnych punktów z komentarzy, które mogą być bardziej przydatne dla przyszłego badacza bez pogłębiania rozmowy o komentarzach.

Odpowiedź 1 :

Próbujesz wyświetlić okno dialogowe po wyjściu z działania.

Odpowiedź 2

Ten błąd może być nieco mylący w niektórych okolicznościach (chociaż odpowiedź jest nadal całkowicie dokładna) - tj. W moim przypadku nieobsługiwany wyjątek został zgłoszony w AsyncTask, co spowodowało zamknięcie działania, a następnie otwarty progressdialog spowodował ten wyjątek .. więc „prawdziwy” wyjątek był nieco wcześniej w dzienniku

Odpowiedź 3

Wywołaj metodęISSISS () w instancji Dialog utworzonej przed wyjściem z działania, np. W onPause () lub onDestroy ()

Alex Volovoy
źródło
2
@Override public void onStop () {if (dialog! = Null) {dialog.dismiss (); dialog = null; }}
Md.Tarikul Islam
14
Nawet po 8 latach jest to nadal aktualne! Wystąpił wyjątek, ponieważ działanie zostało zamknięte podczas próby wyświetlenia mojego AlertDialog (więc Odpowiedź 2). W końcu dowiedziałem się, że aplikacja dodawała do sceny obiekt „zerowy” (nie powinno się to zdarzyć, ale tak się stało), ale nie dawało to dodatkowego wyjątku, a całość maskowała „wyciek” zamiast okna ”.
Neph
Czy można skanować w poszukiwaniu wszystkich otwartych okien dialogowych i zamykać je wszystkie w onStop ()? Po kliknięciu elementów generuję okna dialogowe w widoku listy. Nie jestem pewien, jak pobrać ich odwołanie z OnStop.
Myoch
1
Odpowiedź 3 jest najlepszym rozwiązaniem. pracował dla mnie bardzo dobrze. Dzięki kaze, Alex !!
amit bansode
dodatkowa wskazówka, jeśli wyświetlasz okno dialogowe w pętli, upewnij się, że pętla została zakończona po zakończeniu aktywności
Thecarisma
405

Rozwiązaniem jest wezwanie dismiss()na Dialogutworzony w viewP.java:183przed opuszczeniem Activity, np onPause(). Wszystkie Windows & Dialogs powinny zostać zamknięte przed opuszczeniem Activity.

molnarm
źródło
3
Więc kiedy użytkownik obraca telefon, wszystkie okna dialogowe powinny zostać odrzucone? To nie brzmi dobrze.
LarsH,
@LarsH, jak widzisz, moja odpowiedź została napisana ponad 7 lat temu, i wtedy była to zdecydowanie prawda. Nie pracuję już z Androidem, ale na podstawie tego, co widzę w dokumentacji , może tak być, ale Android przeszedł długą drogę (wprowadził Fragmenty tylko po to, aby wymienić), więc prawdopodobnie jest teraz łatwiej.
molnarm
108

Jeśli używasz AsyncTask, prawdopodobnie ten komunikat dziennika może wprowadzać w błąd. Jeśli spojrzysz na swój dziennik, możesz znaleźć inny błąd, prawdopodobnie w twojej doInBackground()metodzie AsyncTask, który powoduje, że twój prąd Activitywysadza się w powietrze, a zatem po AsyncTaskpowrocie .. cóż, znasz resztę. Niektórzy inni użytkownicy już to wyjaśnili tutaj :-)

ggomeze
źródło
22
Czasami w takim przypadku nie widzę prawdziwego wyjątku. Aby znaleźć prawdziwy wyjątek, po prostu skomentuj progressDialog.show () i uruchom aplikację ponownie .. teraz widzisz.
Utknąłem
Cześć ludzie! Jak wspomniano powyżej przez @Stuck, nie widzę również prawdziwego wyjątku. Co zrobiłem? Ja go śledzone za pomocą punktów Rozstania i odkryłem, że był przy użyciu odniesienie klasy Application wewnątrz metody doInBackgroundz AsyncTaskklasy, ale bez zadeklarować w AndroidManifestpliku przy użyciu właściwości android:nametakiego: android:name="my.package.MyApplicationClass". Dobrą praktyką podczas korzystania z AsyncTaskniego jest zawsze pamiętaj o utworzeniu alertu w metodzie onPreExecutei odrzuceniu go onPostExecute.
GFPF,
66

Wywołałem ten błąd przez pomyłkowe wywołanie hide()zamiast dismiss()na AlertDialog.

Mark Phillip
źródło
4
Dokładnie to, co mi się przydarzyło. Wywołanie hide (), a następnie ustawienie wartości null na okno dialogowe również nie jest prawidłową alternatywą.
Lucas Tulio
Naprawdę poznałbym za tym problem. Ale wywołanie metodyISSISS () pomogło mi!
Karoly
59

Możesz uzyskać ten wyjątek, po prostu przez zwykły / głupi błąd, (na przykład) przypadkowo dzwoniąc finish()po wyświetleniu AlertDialog, jeśli przegapisz instrukcję przerwania w instrukcji przełączania ...

   @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;
        }
    }

finish()Metoda będzie zamknąć Activity, ale AlertDialognadal wyświetla!

Więc kiedy wpatrujesz się uważnie w kod, szukasz złych wątków lub skomplikowanego kodowania i tym podobnych, nie trać z lasu lasu. Czasami może to być coś tak prostego i głupiego jak brakująca instrukcja break. :)

Adrian Romanelli
źródło
Mniej więcej dokładnie mój problem. Wywoływane na koniec w onError po utworzeniu okna dialogowego, a nie w onClick dla przycisku odrzucenia.
jbass
45

Wszystkie odpowiedzi na to pytanie były poprawne, ale trochę mylące dla mnie, aby zrozumieć, dlaczego. Po około 2 godzinach gry powód tego błędu (w moim przypadku) uderzył mnie:

Po przeczytaniu innych odpowiedzi wiesz już, że X has leaked window DecorView@d9e6131[]błąd oznacza, że ​​okno dialogowe było otwarte po zamknięciu aplikacji. Ale dlaczego?

Możliwe, że aplikacja uległa awarii z innego powodu, gdy okno dialogowe było otwarte

Prowadzi to do zamknięcia aplikacji z powodu błędu w kodzie, co powoduje, że okno dialogowe pozostaje otwarte w tym samym czasie, co aplikacja zamknięta z powodu innego błędu.

Przejrzyj swoją logikę. Rozwiąż pierwszy błąd, a następnie drugi błąd sam się rozwiążewprowadź opis zdjęcia tutaj

Jeden błąd powoduje inny, co powoduje inny, np. DOMINOS!

Ruchir Baronia
źródło
2
Nie mogę uwierzyć, że ma to tylko jeden głos .. lub jesteśmy po prostu naprawdę kiepscy w programowaniu hahaha Spodobała mi się również twoja analogia do domina
użytkownik2161301
Rozwiąż pierwszy błąd, a drugi błąd nie wystąpi . Ta analogia mi pomogła.
itabdullah
Nie jest to całkowicie słuszne, przypadki takie jak obrót telefonu mogą również powodować obrót „aktywności”.
Sreekanth Karumanaghat
36

Ten problem pojawia się podczas próby wyświetlenia okna dialogowego po wyjściu z działania.

Właśnie rozwiązałem ten problem, zapisując następujący kod:

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

Zasadniczo, od której klasy zacząłeś progressDialog, zastąp metodę onDestroy i zrób to w ten sposób. Rozwiązano problem z „Aktywnością wyciekło okno”.

Shoaib Ahmed
źródło
Nie można zagwarantować, że onDestroy zostanie wywołany. Lepiej umieścić ten kod w onPause lub
onStop
19

Ostatnio napotkałem ten sam problem.

Przyczyną tego problemu jest zamknięcie działania przed zamknięciem okna dialogowego. Istnieje wiele przyczyn takiego stanu rzeczy. Te wymienione w powyższych postach są również poprawne.

Wpadłem w sytuację, ponieważ w wątku wywoływałem funkcję, która rzucała wyjątek. Z powodu którego okno było usuwane, a zatem wyjątek.

Tuszar
źródło
16

Zamknij okno dialogowe, gdy aktywność zostanie zniszczona

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}
Muhammad Aamir Ali
źródło
jeśli pDialog ma wartość NULL, spowoduje to wyświetlenie błędu podczas zapytania o stan okna zerowego
Jonathan Dunn
1
nie, nie będzie @JonDunn, ponieważ Java nie przetworzy drugiego boolean, jeśli pierwszy jest fałszywy
matdev
13

To może pomóc.

if (! isFinishing()) {

    dialog.show();

    }
piaszczysty
źródło
2
Wśród setek podobnych odpowiedzi nikt nie pokazuje, jak sprawdzić, czy istnieje system Windows. Więc oszczędzasz mi trochę czasu na znalezienie sposobu na zrobienie tego. Dzięki.
kolyaseg
11

Miałem ten sam niejasny komunikat o błędzie i nie miałem pojęcia, dlaczego. Biorąc pod uwagę wskazówki z poprzednich odpowiedzi, zmieniłem swoje wywołania inne niż GUI na mDialog.finish () na mDialog.dismiss () i błędy zniknęły. Nie miało to wpływu na zachowanie mojego widgetu, ale było niepokojące i mogło oznaczać ważny wyciek pamięci.

Melinda Green
źródło
Zauważyłem, że robiłem mDialog.hide () przed wywołaniem zakończenia (). Zmiana na mDialog.dismiss () załatwiła sprawę.
maja
11

Otrzymywałem te dzienniki w mojej aplikacji odtwarzacza wideo. Te wiadomości zostały wyrzucone, gdy odtwarzacz wideo był zamknięty. Co ciekawe, logi te pobierałem raz na kilka serii w losowy sposób. Również moja aplikacja nie dotyczy progressdialog. Wreszcie obejrzałem ten problem z poniższą implementacją.

@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();
}

Zastąp opcję „ OnPausecall call” mVideoView.pause()i „set visibilityto” GONE. W ten sposób mogłem rozwiązać problem z Activity has leaked windowbłędem dziennika.

InvisiblePoint
źródło
Mam również ten sam problem. dodałem te wiersze kodu do mojego kodu, ale nie działał i wyświetla ten sam błąd „android.view.WindowLeaked, który został pierwotnie dodany”, a także nie odtwarza wideo i daje komunikat „Nie można odtworzyć wideo”
User42590
10

Miałem ten sam problem i znalazłem tę stronę i chociaż moja sytuacja była inna, zadzwoniłem finishz ifbloku, zanim zdefiniował pole alertu.

Tak więc zwykłe dzwonienie dismissnie zadziałałoby (bo jeszcze tego nie zrobiono), ale po przeczytaniu odpowiedzi Alexa Volovoya i zrozumieniu, że to ona spowodowała alarm. Próbowałem dodać instrukcję return zaraz po zakończeniu wewnątrz tego ifbloku i to rozwiązało problem.

Myślałem, że kiedy nazwiesz „koniec”, wszystko zatrzymało się i skończyło się w tym miejscu, ale tak się nie dzieje. Wydaje się, że kończy się na końcu bloku kodu, w którym się kończy.

Tak więc, jeśli chcesz zaimplementować sytuację, w której czasami kończy się przed wykonaniem kodu, musisz umieścić instrukcję return zaraz po zakończeniu lub będzie kontynuowała działanie i działała tak, jakby koniec został wywołany na końcu blok kodu nie w miejscu, w którym go nazwiesz. Właśnie dlatego dostaję te wszystkie dziwne błędy.

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();
}

Jeśli nie umieścisz zwrotu zaraz po tym, jak wezwałem tam wykończenie, będzie to działało tak, jakbyś nazwał go po tym, alert.show();a zatem powiedziałoby, że okno jest nieszczelne, kończąc zaraz po tym, jak pojawiło się okno dialogowe. nie w tym przypadku, nadal tak jest.

Pomyślałem, że dodam to tutaj, ponieważ pokazuje, że polecenie zakończenia działało inaczej, niż myślałem, że tak, i sądzę, że są inni ludzie, którzy myślą tak samo, jak ja, zanim to odkryłem.

Kit Ramos
źródło
7

To nie jest odpowiedź na pytanie, ale odnosi się do tematu.

Jeśli działanie zdefiniowało atrybut w Manifeście

 android:noHistory="true"

następnie po wykonaniu onPause () kontekst działania zostaje utracony. Więc wszystkie widoki używające tego kontekstu mogą dawać ten błąd.

Zabójca
źródło
Można odnosić się do czegoś podobnego progessdialog.show().. i progressdialog.hide()w asynctasktej samej działalności, a nie onPause()z activity?? spójrz na mój problem ... stackoverflow.com/questions/39332880/…
Bhuro
1
działa dla mnie idealnie: android: noHistory = "true"
Shohel Rana
6

Nie tylko próbuj wyświetlić alert, ale można go również wywołać po zakończeniu określonego wystąpienia aktywności i próbie rozpoczęcia nowej aktywności / usługi lub próby jej zatrzymania.

Przykład:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Kulbhushan Chaskar
źródło
6

Zasadniczo ten problem występuje z powodu okna dialogowego postępu: możesz rozwiązać ten problem, używając jednej z następujących metod w swoim działaniu:

 // 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
źródło
5

Wystąpił problem polegający na tym, że zakończyłem działanie, gdy program ProgressDialog był nadal wyświetlany.

Najpierw ukryj okno dialogowe, a następnie zakończ działanie.

LeonS
źródło
5

Wypróbuj ten kod:

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

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

}
tinku
źródło
progressdialog.dismiss();może to stworzyć wyjątek NullPointerException.
tpk
5

Może się tak zdarzyć, jeśli masz błąd w doInBackground()działaniu i masz ten kod.

Spróbuj w końcu dodać okno dialogowe. Na początku sprawdź i napraw doInBackground()funkcję

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
źródło
5

To zdarzyło się do mnie, kiedy używam ProgressDialogw AsyncTask. Właściwie używam hide()metody w onPostExecute. Na podstawie odpowiedzi z @Alex Volovoy muszę korzystać dismiss()z ProgressDialogusunięcia go w onPostExecute i jego zrobienia.

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

progressDialog.dismiss(); // Use it
SANAT
źródło
To nie jest tak naprawdę pełna odpowiedź. Istnieją dwa sposoby na wyciek okna dialogowego. 1) Jeśli masz AsyncTaski pokazujesz Dialog, to dzieje się coś, co wywołuje Activitywywołanie onPause()(być może logika w twoim AsyncTask, jak słuchacz, wtedy wycieknie. 2) Jak wspomniano powyżej, to, Dialogco zostało utworzone za pomocą tego, Activity Contextnigdy nie jest zwolniony i Activityidzie dalej.
tricknology
5

Activity has leaked window that was originally added...Błąd „ ” występuje, gdy próbujesz pokazać alert po Activityskutecznym finished.

Masz dwie opcje AFAIK:

  1. Przemyśleć logowanie swojego wpisu: wezwanie dismiss()na dialogzanim faktycznie wychodzenia swoją aktywność.
  2. Umieść dialogw innym wątku i uruchom na nim thread(niezależnie od prądu activity).
Kyle Clegg
źródło
5

oto rozwiązanie, gdy chcesz odrzucić AlertDialog, ale nie chcesz zachować odwołania do niego w działaniu.

rozwiązanie wymaga posiadania zależności androidx.lifecycle w swoim projekcie (uważam, że w momencie komentarza jest to powszechny wymóg)

pozwala to na delegowanie odrzucenia okna dialogowego do obiektu zewnętrznego (obserwatora) i nie musisz się już tym przejmować, ponieważ jest automatycznie wypisywane po zakończeniu aktywności. (tutaj jest dowód: https://github.com/googlecodelabs/android-lifecycles/issues/5 ).

więc obserwator zachowuje odniesienie do okna dialogowego, a aktywność zachowuje odniesienie do obserwatora. kiedy zdarza się „onPause” - obserwator zamyka okno dialogowe, a gdy zdarza się „onDestroy” - aktywność usuwa obserwatora, więc nie dochodzi do wycieku (cóż, przynajmniej nie widzę już błędu w 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
źródło
4

Wyjątki związane z wyciekaniem okien mają dwa powody:

1) wyświetlenie okna dialogowego, gdy kontekst działania nie istnieje, aby go rozwiązać, powinieneś pokazać okno dialogowe tylko wtedy, gdy masz pewność, że działanie istnieje:

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

2) nie odrzuć odpowiednio okna dialogowego, aby rozwiązać, użyj tego kodu:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}
Sherry
źródło
4

Musisz zrobić Progressdialogobiekt onPreExecutemetodą AsyncTaski powinieneś dismissto zrobić onPostExecutemetodą.

ammad
źródło
4

Najlepszym rozwiązaniem jest dodanie okna dialogowego podczas próby złapania i odrzucenia okna dialogowego, gdy wystąpi wyjątek

Po prostu użyj poniższego kodu

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }
Ness Tyagi
źródło
3
czy okno dialogowe nie będzie puste po zakończeniu połączenia? Myślę, że również dialog.dismiss()spowoduje błąd
Ashu Kumar
3

W moim przypadku powodem było to, że zapomniałem dołączyć pozwolenie do pliku manifestu Androida.

Jak się dowiedziałem? Cóż, tak jak @Bobby mówi w komentarzu pod zaakceptowaną odpowiedzią, po prostu przewiń dalej do swoich dzienników, a zobaczysz pierwszy powód lub zdarzenie, które naprawdę spowodowało wyjątek. Najwyraźniej komunikat „Aktywność wyciekła okno, które zostało pierwotnie dodane” to tylko wyjątek wynikający z pierwszego wyjątku.

Matthew Quiros
źródło
3

Wypróbuj poniższy kod, zadziała za każdym razem, gdy odrzucisz dialog postępu i zobaczysz, czy jego instancja jest dostępna, czy nie.

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
Deweloper
źródło
2

Najlepszym rozwiązaniem jest umieszczenie tego przed pokazaniem progressbarlubprogressDialog

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

  //Show Your Progress Dialog

}
Ali Akram
źródło
To mi nie działa. Mam Dialog.show () po odpowiedzi z wywołania HTTP i kiedy w międzyczasie obracam ekran Aktywność jest odłączona, ale wygląda na to, że isShown == true przed Dialog.show (), a następnie Dialog ulega awarii pomimo tej kontroli
Michał Ziobro
1

Upewnij się tylko, że twoja aktywność nie niespodziewanie się kończy z powodu wyjątków zgłoszonych gdzieś w kodzie. Zasadniczo dzieje się tak w zadaniu asynchronicznym, gdy działanie napotyka wymuszone zamknięcie w metodzie doinBackground, a następnie asynctask powraca do metody onPostexecute.

Manas Ranjan
źródło
1

Mam na to inne rozwiązanie i chciałbym wiedzieć, czy wydaje się to dla ciebie ważne: zamiast zwolnienia w onDestroy, który wydaje się być wiodącym rozwiązaniem, rozszerzam 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;
  }

Jest to preferowane, AFAIC, ponieważ nie musisz utrzymywać dialogu postępu jako członek, po prostu odpal (pokaż) i zapomnij

Kalisky
źródło