Wpis z mikrobloga

Mirki spod tagu #androiddev i #java potrzebuje małej pomocy bo od 2 dni z tym walczę i nie daję rady.
Mam fragment (NewShiftFragment), posiadający pole EditText po którego kliknięciu wyświetla się DialogFragment z możliwością wybrania daty. Po wybraniu daty jest ona przekazywana poprzez listener do MainActivity z kolei w MainActivity wywoływana jest metoda, która znajduje się w klasie NewShiftFragment - ustawia ona tekst na przekazaną datę.

W skrócie wygląda to tak:

NewShiftFragment -> (klikniecie w dateEditText) -> odpala się DatePickerDialogFragment -> (wybieram date i naciskam OK) -> data przekazywana jest za pomocą listenera do metody onDateSet w MainActivity -> w niej wywolywana jest metoda newShiftFragment.setDateEditText(formattedDate) -> w tej metodzie wywoływana jest tylko jedna linia dateEditText.setText(date); -> pole w EditText zostaje ustawione na daną datę
Wszystko to działa dobrze dopóki chociaż raz nie zmienię orientacji ekranu. Wtedy wszystkie kroki wykonują się poprawnie oprócz ostatniego czyli dateEditText.setText(date) - dostaję wtedy wyjątek "java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference".

Dlaczego tak się dzieje? Kiedy sprawdzam dateEditText w metodzie onCreateView to ona nigdy nie jest null'em (po zmianie orientacji również), dlaczego zatem w metodzie setDateEditText się on pojawia? Czy ma to coś wspólnego z tym, że ta metoda jest wywoływana z innej klasy (MainActivity)? Jeśli tak to dlaczego dopóki nie zmienię orientacji to wszystko jest ok?

MainActivity:
http://pastebin.com/gcTnyXUx

NewShiftFragment:
http://pastebin.com/L8TvSV7E

#naukaprogramowania
  • 14
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@w0If: Próbowałem ale kiedy ona tam jest to nie jest widoczna w metodzie onDateSet. Poza tym wydaje mi się, że z tą instancją jest wszystko ok bo program normalnie przechodzi dalej do metody newShiftFragment.setDateEditText(formattedDate) i dopiero w tej metodzie wywołanie dateEditText.setText(date) powoduje błąd. Zapomniałem dodać, że do tej metody również normalnie dochodzi String (sprawdzone logiem).
  • Odpowiedz
@w0If: Odpalam program, zmieniam datę a następnie obracam ekran i zostaje data ta sama na którą wcześniej zmieniłem co wydaje mi się dziwne bo metoda onCreateView jest wykonywana za każdym razem po obrocie ekranu. Nie jestm przypadkiem tak, że wcześniej ustawione parametry zostaje przekazywane po każdym obrocie w savedInstanceState?
  • Odpowiedz
@w0If: Zauważyłem, że polecenie dateEditText.setText(nowDate.toString()) miałem zdublowane bo występuje też w metodzie configureDefaultFields(), jednak nie miało to wpływu na dany problem bo on nadal występuje.

Chciałbym też dodać, że taki sam problem występuje przy metodzie setShiftEditText(String shiftName) z tym, że tutaj nie pobieram daty tylko element z listy (również z DialogFragment).
  • Odpowiedz
@iwannagethigh: Na szybko - po zmianie orientacji ekranu Activity przebudowuje cały widok na nowo. Jeśli przekazujesz do Listenera EditText, to po zmianie orientacji tego pola już nie będzie (przy okazji powstaje mały wyciek pamięci).
A tym, że EditText zapamiętuje wartość się nie przejmuj - to normalne. Może i widok się przeudowuje, ale wartość dla jego id'ka jest zapisana.
  • Odpowiedz
@Dante651: Dzięki za odpowiedź. To, że widok się przebudowuje to wiem. EditText nie przekazuje do listenera tylko datę (w postaci 3 intów, które w metodzie listenera są zamieniane na String i wtedy przekazywane do fragmentu). Zresztą nie muszę nic przekazywać - wystarczy, że zaraz po uruchomieniu aplikacji zmienię orientację ekranu i dopiero wtedy spróbuje zmienić datę to aplikacja i tak się crashuje, natomiast jeśli nie zmienie orientacji to mogę sobie
  • Odpowiedz
@iwannagethigh: Przyjrzałem się kodowi i jak na moje winowajcą jest:

private final NewShiftFragment newShiftFragment = new NewShiftFragment();
Zamiast operować na lokalnej zmiennej reprezentującej fragment powinieneś wyciągnąć fragment z FragmentManagera przez Tag lub Id, wtedy możesz go rzutować na NewShiftFragment i wywołać odpowiednią metodą. Ja bym tego spróbował ;-)
  • Odpowiedz
Poza tym wydaje mi się, że z tą instancją jest wszystko ok bo program normalnie przechodzi dalej do metody newShiftFragment.setDateEditText(formattedDate) i dopiero w tej metodzie wywołanie dateEditText.setText(date) powoduje błąd.


@Dante651: Aktualnie jestem w pracy więc sprawdzę to dopiero jutro, jednak nie wydaje mi się aby to pomogło. Kilka komentarzy wyżej już napisałem

"Poza tym wydaje mi się, że z tą instancją jest wszystko ok bo program normalnie przechodzi dalej do
  • Odpowiedz
@iwannagethigh:
Kluczowy fakt:

Przy zmianie konfiguracji fragment nie jest niszczony -> zostaje z powrotem automatycznie dodany do aktywności która jest odtwarzana.


Prześledźmy co się dzieje w
  • Odpowiedz
@RufuSx: Kolego mam jeszcze pytanko do Ciebie. Błąd o którym była mowa załatwiłem linijką "outState.putInt(NAVITEMID, mNavItemId);" w przysłoniętej metodzie onSaveInstanceState w activity. Pojawił się jednak następny problem. Po zmianie orientacji nie zapisują się pola danych we fragmencie, które wcześniej uzupełniłem (tzn cały widok odtwarza się na nowo - łącznie z domyślnymi wartościami). Postanowiłem więc zapisać ich stan w metodzie onSaveInstanceState fragmentu "outState.putString(DATE, dateEditText.getText().toString());" natomiast w onCreateView je odtworzyć
  • Odpowiedz
@iwannagethigh: Widzę, że dalej nie rozumiesz :P Przy obrocie ekranu fragment automatycznie się odtwarza. Kolejność wykonywania metod jest taka:

1) Activity onCreate()
2) Fragment stary onCreate()
3) Fragment stary onCreateView()
4) Fragment
  • Odpowiedz