2010-02-26 18 views
12

1) I uruchomić zadanie tła (poprzez AsyncTask)Odrzuć okno po zmianie orientacji ekranu

new FindJourneyTask().execute(); // FindJourneyTask extends AsyncTask 

2) Jeszcze w głównym wątku (tuż przed nowy wątek jest uruchomiony) utworzyć dialog z ShowDialog (dialogId)

// this method is in FindJourneyTask 
protected void onPreExecute() { 
    showDialog(DIALOG_FINDING_JOURNEY); 
} 

3) zmiany orientacji ekranu, a aktywność jest odtwarzany

4) w jaki sposób mogę teraz zamknąć to okno z FindJourneyTask? Wywołanie metody dismissDialog (dialogId) nic nie robi.

// this method is in FindJourneyTask 
protected void onPostExecute(FindJourneyResult result) { 
    dismissDialog(DIALOG_FINDING_JOURNEY); // does nothing 
} 
+0

Opublikuj swój kod, abyśmy mogli zobaczyć, co robisz źle. –

Odpowiedz

22

Jest to powszechny problem i nie ma naprawdę dobrych rozwiązań. Problem polega na tym, że przy zmianie orientacji ekranu całe działanie zostaje zniszczone i odtworzone. W tym samym czasie okno dialogowe, które poprzednio miałeś, jest ponownie tworzone w nowym działaniu, ale stare zadanie w tle nadal odnosi się do starej czynności, gdy próbuje zamknąć okno dialogowe. Powoduje to, że odrzuca dialog, który był dawno zniszczony, zamiast odrzucać dialog, jaki wytworzyła nowa orientacja.

Istnieją trzy podstawowe rozwiązania:

  1. zastąpić domyślny kod orientacja-manipulacja tak, że aktywność nie ulega zniszczeniu podczas obrotu. Jest to prawdopodobnie najmniej satysfakcjonująca odpowiedź, ponieważ blokuje wiele kodów, które są automatycznie uruchamiane po zmianie orientacji.

  2. Utwórz statyczną zmienną składową swojej aktywności, która odwołuje się do samej czynności, dzięki czemu możesz zadzwonić pod numer STATIC_ACTIVITY_VARIABLE.dismissDialog().

  3. Kodowanie rozwiązania, w którym zadanie w tle śledzi bieżącą aktywność i aktualizuje się w razie potrzeby.

Te trzy roztwory zostały szczegółowo omówione tutaj: http://groups.google.com/group/android-developers/browse_thread/thread/bf046b95cf38832d/

+0

Zrobiłem mój dialog jako zmienną statyczną w mojej działalności i teraz działa idealnie. na przykład static AlertDialog dlg_error = null; – Kevin

10

istnieje lepsze rozwiązanie tego problemu, które polega na zastosowaniu obecnie fragmenty.

Jeśli utworzysz okno dialogowe za pomocą DialogFragment, ten fragment będzie odpowiedzialny za utrzymanie cyklu życia okna dialogowego. Po wyświetleniu okna dialogowego podajesz znacznik fragmentu (DialogFragment.show()). Kiedy chcesz uzyskać dostęp do okna dialogowego, po prostu poszukaj potrzebnego DialogFragment przy użyciu FragmentManager.findFragmentByTag zamiast odniesienia do samego okna dialogowego.

W ten sposób, jeśli urządzenie zmieni orientację, otrzymasz nowy fragment zamiast starego, a wszystko będzie działać.

Oto niektóre kodu również oparte na @peresisUser odpowiedź:

public void onSaveInstanceState(Bundle outState) { 
    AppCompatActivity activity = (AppCompatActivity) context; 
    FragmentManager fragmentManager = activity.getSupportFragmentManager(); 
    DialogFragment dialogFragment = (DialogFragment) fragmentManager.findFragmentByTag("your_dialog_tag"); 
    if(dialogFragment!=null) { 
     Dialog dialog = dialogFragment.getDialog(); 
     if(dialog!=null && dialog.isShowing()) { 
     dialogFragment.dismiss(); 
     } 
    } 
} 
+1

Mam ten sam problem, nawet używając fragmentów. Po odtworzeniu działania i próbie znalezienia fragmentu za pomocą znacznika, zawsze otrzymuję odwołanie zerowe w oknie dialogowym pokazanym w nowym działaniu O_o – fr4gus

+0

@ fr4gus To prawdopodobnie błąd, musisz eksperymentować z rzeczami, aby znaleźć obejście. – Malcolm

4

Jest to długo po tym padło pytanie i odpowiedział, ale natknąłem się tym problemem także i chciał podzielić się rozwiązanie ...

Sprawdzam metodę onSavedInstance(), która działa przy zmianie orientacji, niezależnie od tego, czy dialog jest wyświetlany, czy nie, z dialog.isShowing(), i przekazuje go do zmiennej outState. Następnie w swoim onCreate(), sprawdzasz ten var, jeśli to prawda. Jeśli tak, po prostu odrzuć okno dialogowe.Odrzuć()

Mam nadzieję, że to pomoże innym :()

Powiązane problemy