2011-11-27 15 views
19

Ostatnio przekonwertowałem Moje działania na fragmenty.Fragmenty wymieniane podczas wykonywania zadania AsyncTask - Wyjątek NullPointerException na getActivity()

Używając czegoś podobnego do nawigacji w karcie fragmenty są zastępowane, gdy użytkownik wybierze inną kartę. Po wypełnieniu fragmentu uruchamiam co najmniej jedną AsyncTask, aby uzyskać pewne informacje z Internetu. Jednak - jeśli użytkownik przełączy się na inną kartę tak jak doBackground-metoda z mojego AsyncTask jest wykonywany - fragment jest zastąpiony a więc jestem coraz NullPointerException w zaznaczonych wierszach:

@Override 
protected Object doInBackground(Object... params) { 
    ... 
    String tempjson = helper.SendPost(getResources().getText(R.string.apiid)); //ERROR: Fragment not attached 
    ... 
} 

protected onPostExecute(Object result) { 
    ... 
    getActivity().getContentResolver() //NULLPOINTEREXCEPTION 
    getView().findViewById(R.id.button) //NULL 
    ... 
} 

getActivity() i getResources() powoduje błąd, ponieważ mój Fragment jest zastępowany.

Czego próbowałem:

  • anulować Wywołanie metody na moim AsyncTask (nie będzie naprawić pierwszy błąd, ani drugi błąd, jeśli fragment otrzymuje podczas onPostExecute() jest wykonywany)
  • sprawdzenie czy getActivity() jest null lub dzwoniąc this.isDetached() (a nie prawdziwy dylemat i że muszę to sprawdzić, gdy zadzwonię getActivity() i tak dalej)

Moje pytanie brzmi: jaki byłby najlepszy sposób na pozbycie się problemów związanych z AsyncTask? Te problemy nie wystąpiły podczas używania działań, ponieważ nie zostały "zabite"/odłączone przy zmianie karty (co spowodowało zwiększenie użycia pamięci - powodem, dla którego lubię przełączać się na fragmenty)

Odpowiedz

18

Od AsyncTask działa w tle Twój fragment może odłączyć się od macierzystej aktywności przed zakończeniem. Jak się dowiedziałeś, możesz użyć isDetached(), by sprawdzić. Nie ma w tym nic złego i nie musisz za każdym razem sprawdzać, tylko rozważ fragmenty i cykle aktywności.

Dwa inne alternatywy:

  • użycie ładowarki, są one przeznaczone do gry ładniejszy z fragmentami
  • Najedź AsyncTask załadunku do interfejsów działalności rodzic i stosowanie oddzielić od fragmentów. Aktywność będzie wiedziała, czy fragment istnieje, czy nie, i podejmie odpowiednie działania (przez ewentualne odrzucenie wyniku, jeśli fragment zniknie).
+8

należy użyć isDetached() tylko wtedy, gdy samodzielnie oddzieliłeś fragment. W przeciwnym razie powinieneś użyć metody isAdded() do obsługi przypadków, w których system zniszczył połączenie między Twoją aktywnością a fragmentem. – pcans

+0

@Nikolay Elenkov, w jaki sposób cykl życia może uniknąć sprawdzania za każdym razem przed wywołaniem aktywności? – Bear

-1

Czy próbowałeś wywołać setRetainInstance(true); w funkcji swojej klasy fragmentów?

+1

To nie pomaga w tym przypadku, problemy są takie same. Na razie rozwiązałem go, tworząc pola dla działania i widoku oraz ustawiając je w 'onActivityCreated()' przy użyciu 'view = getView()' i tak dalej. – Boni2k

4

Dziś mam w obliczu tego samego problemu: kiedy zmienił fragment wyświetlana jeśli AsyncTask jeszcze nie skończył, a on próbuje uzyskać dostęp do view aby wypełnić go z niektórymi więcej elementów, to zwróci NullPointerException.

Rozwiązałem problem przesłonięcia jednej z metod cyklu życia fragmentów: onDetach(). Ta metoda jest wywoływana w momencie przed odłączeniem fragment od activity.

To, co musisz zrobić, to zadzwonić na cancel() metodę na swoim AsyncTask.Spowoduje to zatrzymanie wykonywania zadania, aby uniknąć NullPointerExecption.

Oto próbka onDetach():

@Override 
public void onDetach() { 
    super.onDetach(); 
    task.cancel(true); 
} 

sprawdzać tę stronę, aby uzyskać więcej informacji na temat fragmentów cyklu: http://developer.android.com/reference/android/app/Fragment.html#Lifecycle I to by zobaczyć więcej o anulowanie zadania: http://developer.android.com/reference/android/os/AsyncTask.html

+0

Dziękuję, dziękuję bardzo. To naprawiło mój problem, który dręczył mnie przez tydzień! –

Powiązane problemy