6

Witam Pracuję nad aplikacją korzystającą z map.Zwolniony fragment okna pojawia się ponownie po wznowieniu aplikacji.

Używam aktywności fragmentarycznej i fragmentu o nazwie Fragment-A.

W Fragment-A znajduje się przycisk, po kliknięciu przycisku pojawia się fragment Dialogu, wyświetla mapę z wcześniejszą lokalizacją otrzymaną z serwera.

Powiedzmy, że ten fragment okna dialogowego to DialogFragment-B.

Ma przycisk do zamknięcia, przycisk do nawigacji do aplikacji mapy Google, aby uzyskać wskazówki.

Jeśli użytkownik przejdzie do DialogFragment-B i powróci do Fragmentu-A, klikając przycisk zamykania, wszystko działa poprawnie.

Ale jeśli użytkownik kliknie przycisk Wstecz, istniejący fragment okna zostanie zamknięty, a aplikacja będzie działać normalnie.

Ale jeżeli użytkownik nacisnął przycisk home lub otrzymał telefon i onResume nazywa chociaż DialogFragment-B została zwolniona wcześniej, to pojawia się ponownie i naciskając blisko wywala aplikację z wyjątku null pointer

Oto mój kod, aby otworzyć DialogFragment-B.

FragmentManager fm = getFragmentManager(); 
    FragmentTransaction ft = fm.beginTransaction(); 
    android.app.Fragment prev = fm.findFragmentByTag(MY_MAP); 
    if (prev != null) { 
     ft.remove(prev); 
    } 
    MyMapFragmentDialog newFragment = MyMapFragmentDialog 
      .newInstance(eachPost); 
    newFragment.show(ft, MY_MAP); 

W DialogFragment-B po kliknięciu przycisku zamykania, nazywam MyMapFragmentDialog.this.dismiss();

Proszę, jeśli ktoś napotkał ten problem i pokonał go, poprowadź mnie przez to.

+0

Myślę, że zaniedbujecie zatwierdzenie transakcji: 'ft.remove (prev) .commit()' lub dodaj kolejną linię, np. 'Ft.commit();' –

+0

Wypróbuj 'MyMapFragmentDialog' wewnątrz pętli if. 'Prev' staje się pusty i dodajesz do niego fragment – GoCrazy

Odpowiedz

2

Aktualizacja: odpowiedź Kaliny jest bardziej eleganckim i prostszym rozwiązaniem - jak się domyślałem później!

Jestem stoi ten sam problem w jednym z moich aplikacji, a nie znalezienie odpowiedzi wszędzie, przeszedł do kodu źródłowego klasy DialogFragment, który jest dostępny pod adresem:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/DialogFragment.java#DialogFragment.onDismiss%28android.content.DialogInterface%29

i tam znalazłem prawdopodobną przyczynę napisane w komentarzu, w źródle onDismiss (dialogowego DialogInterface) metoda:

// Note: we need to use allowStateLoss, because the dialog 
// dispatches this asynchronously so we can receive the call 
// after the activity is paused. Worst case, when the user comes 
// back to the activity they see the dialog again. 

Co zrozumiałem z tego jest to, że zwolnienie jest a nie zapisano w stanie instancji, a po wznowieniu działania, natychmiast pokaże je ponownie jako część przywracania stanu instancji - zakładając, że fragment nigdy nie został odrzucony. Będąc asynchronicznego zdarzenia, nie istnieje bezpieczny sposób popełnić odrzucić bez ryzykowania

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 

wyjątek iw konsekwencji awarii, co jest prawdopodobnie dlaczego autorzy klasie wybrał to zrobić w ten sposób.

Rozwiązanie że pracował dla mnie było osobno monitorować stan DialogFragment przez:

  • przechowywanie go w zmiennej klasy (określane tu jako „dialog”)
  • przesłanianie onDismiss (okno DialogInterface) metody i
  • Ustawianie logiczną dialogDismissed flagę prawdziwej

-

@Override 
public void onDismiss(DialogInterface dialog) { 
    // dialogDismissed is a Class level variable in the containing Activity, 
    // must be set to false each time the DialogFragment is shown 
    dialogDismissed = true; 
} 
  • Uwaga: jeśli DialogFragment jest oddzielna klasa, to wtedy metoda w działalności będą musiały być wywoływane z onDismiss to zrobić, być może poprzez utworzenie interfejsu

  • Flaga ta musi być sprawdzona w działaniu onResume() i zmuszony odwołać (po sprawdzeniu, że okno nie jest null):

-

@Override 
public void onResume() { 
super.onResume(); 
//... 
if (dialogDismissed && dialog != null) { 
     dialog.dismiss(); 
    }  
} 
10

miałem ten sam problem i został rozwiązany przez upewniając się nazywam super.onDismiss(dialog) w sposobie mojego DialogFragment podklasy onDismiss.

+0

Miałem ten sam problem, ten naprawiony mój. – qtyq