Używam ACRA do zgłaszania awarii aplikacji. Otrzymywałem View not attached to window manager
komunikat o błędzie i myślałem, że to naprawiłem, pakując pDialog.dismiss();
instrukcję if:
if (pDialog!=null)
{
if (pDialog.isShowing())
{
pDialog.dismiss();
}
}
Zmniejszyło to liczbę View not attached to window manager
wypadków, które otrzymuję, ale wciąż się pojawiają i nie jestem pewien, jak to rozwiązać.
Komunikat o błędzie:
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)
Fragment kodu:
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);
}
}
Oczywisty:
<activity
android:name="pagename.CLASS"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
android:label="@string/name" >
</activity>
Czego brakuje mi, aby powstrzymać katastrofę?
AsyncTask
jest zadeklarowane w środkuActivity
lubFragment
?Odpowiedzi:
Jak odtworzyć błąd:
Settings -> Developer Options -> Don't keep Activities
.AsyncTask
wykonywania iProgressDialog
pokazywania.System operacyjny Android zniszczy działanie, gdy tylko zostanie ukryte. Kiedy
onPostExecute
zostanie wywołany,Activity
będzie w stanie „wykończenia” iProgressDialog
nie będzie do niego przywiązanyActivity
.Jak to naprawić:
onPostExecute
metodzie.ProgressDialog
inonDestroy
. W przeciwnym razieandroid.view.WindowLeaked
zostanie zgłoszony wyjątek. Ten wyjątek zwykle pochodzi z okien dialogowych, które są nadal aktywne po zakończeniu działania.Wypróbuj ten naprawiony kod:
źródło
isDestroyed()
przezisFinishing()
wszystkich interfejsów API dla tego konkretnego celu?isFinishing()
nie ma gwarancjitrue
, że działanie zostanie zniszczone przez system, zobacz dokumentację Działania .// or call isFinishing() if min sdk version < 17
, spotka go ten sam wyjątek. Potrzebujemy więc innego rozwiązania niż ta odpowiedź dla aplikacji działających na API <17.myActivityWeakReference.get() != null && !myActivityWeakReference.get().isFinishing()
Problemem może być to,
Activity
że byłyfinished
lub byłyprogress of finishing
.Dodaj czek
isFinishing
i odrzuć okno dialogowe tylko wtedy, gdy jestfalse
isFinishing: sprawdź, czy czynność jest w trakcie kończenia, albo dlatego, że ją wywołałeś , albo
finish
ktoś inny poprosił o jej zakończenie.źródło
Do
Dialog
tworzenia w aFragment
używam następującego kodu:Używam tego wzorca, aby poradzić sobie ze sprawą, kiedy
Fragment
można odłączyć a odActivity
.źródło
Zobacz, jak działa Kodeks tutaj:
Po wywołaniu zadania asynchronicznego zadanie asynchroniczne działa w tle. to jest pożądane. Teraz to zadanie asynchroniczne ma okno dialogowe postępu dołączone do działania, jeśli zapytasz, jak wyświetlić kod:
Mijasz
Class.this
argument jako kontekst do argumentu. Tak więc okno dialogowe Postęp jest nadal dołączone do działania.Rozważmy teraz scenariusz: jeśli spróbujemy zakończyć działanie za pomocą metody finish (), gdy zadanie asynchroniczne jest w toku, to jest to miejsce, w którym próbujesz uzyskać dostęp do zasobu dołączonego do działania, tj.
progress bar
Kiedy działanie już nie jest tam.Stąd otrzymujesz:
Rozwiązanie tego:
1) Upewnij się, że okno dialogowe zostało zamknięte lub anulowane przed zakończeniem działania.
2) Zakończ działanie, dopiero po zamknięciu okna dialogowego, to znaczy, że zadanie asynchroniczne zostało zakończone.
źródło
Activity
; Android może to zakończyć w dowolnym momencie. Więc # 2 nie ma sensu.Oparty na odpowiedzi @erakitin, ale również kompatybilny z wersjami Androida <poziom API 17. Niestety Activity.isDestroyed () jest obsługiwany tylko od poziomu API 17, więc jeśli kierujesz na starszy poziom interfejsu API, taki jak ja, musisz sprawdź to sam. Po tym nie mam
View not attached to window manager
wyjątku.Przykładowy kod
źródło
skieruj to .
źródło
Zastąp onConfigurationChanged i odrzuć okno dialogowe postępu. Jeśli okno dialogowe postępu zostanie utworzone w trybie pionowym, a odrzucone w układzie poziomym, wyświetli się błąd Widok niepowiązany z menedżerem okien.
Zatrzymaj także pasek postępu i zatrzymaj zadanie asynchroniczne w metodach onPause (), onBackPressed i onDestroy.
źródło
Zastąp onDestroy działania i zamknij okno dialogowe i unieważnij
źródło
Po pierwsze, przyczyną awarii jest indeks decorView o wartości -1, możemy to wiedzieć z kodu źródłowego Androida, jest fragment kodu:
więc otrzymujemy rozdzielczość śledzenia, po prostu oceniamy indeks decorView, jeśli jest większy niż 0, kontynuujemy lub po prostu wracamy i rezygnujemy z odrzucenia, kodujemy w następujący sposób:
źródło
Pomiń tę
dismiss()
metodę:Aby odtworzyć problem, zakończ działanie przed zamknięciem okna dialogowego.
źródło
najlepsze rozwiązanie. Sprawdź pierwszy kontekst jest kontekstem działania lub kontekstem aplikacji, jeśli kontekst działania to tylko sprawdzenie działania jest zakończone, a następnie nie zadzwoń
dialog.show()
lubdialog.dismiss();
Jeśli chcesz dodać więcej czeków, dodaj
dialog.isShowing()
lubdialog !-null
użyj&&
warunku.źródło
Przyczyną tego problemu jest zakończenie aktywności przed wywołaniem funkcji zwalniania. Podejmij wyjątek i sprawdź dokładnie dziennik ADB.
źródło
Mam sposób na odtworzenie tego wyjątku.
Używam 2
AsyncTask
. Jeden wykonuje długie zadanie, a drugi wykonuje krótkie. Po zakończeniu krótkiego zadania zadzwońfinish()
. Po zakończeniu długiego zadania i wywołaniuDialog.dismiss()
następuje awaria.Oto mój przykładowy kod:
Możesz spróbować i dowiedzieć się, jak najlepiej rozwiązać ten problem. Z moich badań wynika, że istnieją co najmniej 4 sposoby, aby to naprawić:
isFinishing()
celu sprawdzenia stanu aktywnościAsyncTask.cancel(false)
wonDestroy()
. Zapobiegnie to wykonaniu asynctask,onPostExecute()
aleonCancelled()
zamiast niego.Uwaga:
onPostExecute()
nadal będzie działać, nawet jeśli zadzwoniszAsyncTask.cancel(false)
na starszy system operacyjny Android, taki jak Android 2.XXMożesz wybrać najlepszy dla siebie.
źródło
Być może inicjujesz pDialog globalnie, a następnie usuń go i zainicjalizuj lokalnie swój widok lub okno dialogowe. Mam ten sam problem, zrobiłem to i mój problem został rozwiązany. Mam nadzieję, że to zadziała u ciebie.
źródło
zamknęliśmy również nasze okno dialogowe dotyczące
onPause
metody lubonDestroy
metodyźródło