Mam fragment (F1) z taką metodą publiczną
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
i tak, kiedy nazywam to (z działania), jest ono zerowe ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
To musi być coś, co robię bardzo źle, ale nie wiem co to jest
getActivity()
. Ponadto, jak tworzysz fragment tego fragmentu? Czy masz go w pliku layout.xml?Odpowiedzi:
commit
planuje transakcję, tzn. nie dzieje się to od razu, ale jest zaplanowane jako praca nad głównym wątkiem, gdy następny wątek będzie gotowy.Sugeruję dodanie
metodę
Fragment
i umieszczenie na niej punktu przerwania i sprawdzenie, kiedy jest wywoływane względem twojego wezwania doasd()
. Zobaczysz, że jest wywoływany po metodzie, w której wykonujesz wezwanie doasd()
wyjścia.onAttach
Połączenia jest, gdyFragment
jest zamocowana do jego aktywności i z tego punktugetActivity()
powróci non null (NB jest równieżonDetach()
połączenie).źródło
onCreateView
lubonActivityCreated
metod. Zastanawiam się, dlaczego należy wywoływać funkcję asd (), gdy ma to miejsce podczas zamieszczania pytań.commitNow()
Najlepszym sposobem na pozbycie się tego jest zachowanie odwołania do aktywności po wywołaniu funkcji onAttach i używanie odwołania do aktywności tam, gdzie jest to potrzebne, na przykład
źródło
onDestroy()
ionDetach()
dlategoonDestroy()
nie jest gwarantowana na miano.Activity
jeśli nie unieważnimy goonDestroy()
?Stało się tak, gdy wywołujesz
getActivity()
inny wątek, który zakończył się po usunięciu fragmentu. Typowym przypadkiem jest wywołaniegetActivity()
(np. Dla aToast
), gdy żądanie HTTP zakończy się (onResponse
na przykład).Aby tego uniknąć, możesz zdefiniować nazwę pola
mActivity
i używać jej zamiastgetActivity()
. To pole można zainicjować w metodzie onAttach () Fragment w następujący sposób:W moich projektach zwykle definiuję klasę bazową dla wszystkich moich fragmentów za pomocą tej funkcji:
Szczęśliwego kodowania,
źródło
Activity
z innego wątku. I tak nie możesz nic z tym zrobić, nawet nie pokazywać Toastu. Dlatego albo najpierw przenieś pracę do głównego wątku, albo w ogóle nie używaj Aktywności.Inne odpowiedzi, które sugerują zachowanie odniesienia do aktywności w onAttach, sugerują bandażowanie prawdziwego problemu. Kiedy getActivity zwraca null, oznacza to, że Fragment nie jest dołączony do Działania. Najczęściej dzieje się tak, gdy działanie zniknęło z powodu rotacji lub działania zostało zakończone, ale we fragmencie nadal jest zarejestrowany jakiś odbiornik wywołania zwrotnego. Kiedy słuchacz zostaje wezwany, jeśli musisz coś zrobić z Działaniem, ale Działanie zniknęło, niewiele możesz zrobić. W swoim kodzie powinieneś po prostu sprawdzić
getActivity() != null
a jeśli go nie ma, nie rób nic. Jeśli zachowasz odniesienie do działania, które zniknęło, uniemożliwisz zbieranie śmieci. Użytkownik nie będzie widział żadnych elementów interfejsu użytkownika, które możesz spróbować. Mogę sobie wyobrazić niektóre sytuacje, w których w detektorze wywołania zwrotnego może być potrzebny kontekst dla czegoś niezwiązanego z interfejsem użytkownika, w takich przypadkach prawdopodobnie bardziej sensowne jest uzyskanie kontekstu aplikacji. Zauważ, że jedynym powodem, dla któregoonAttach
sztuczka nie jest dużym przeciekiem pamięci, jest to, że normalnie po wykonaniu nasłuchiwania oddzwaniania nie będzie już potrzebna i można ją wyrzucać do śmieci wraz z fragmentem, wszystkimi jego widokami i kontekstem działania. Jeśli tysetRetainInstance(true)
istnieje większa szansa na wyciek pamięci, ponieważ pole Działanie również zostanie zachowane, ale po rotacji może to być poprzednie Działanie, a nie bieżące.źródło
Od wersji Androida API 23, funkcja onAttach (działalność związana z aktywnością) jest przestarzała. Musisz użyć onAttach (kontekst kontekstowy). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
Aktywność jest kontekstem, więc jeśli możesz po prostu sprawdzić, czy kontekst jest Aktywnością i przesłać go w razie potrzeby.
źródło
PJL ma rację. Skorzystałem z jego sugestii i właśnie to zrobiłem:
zdefiniowane zmienne globalne dla fragmentu:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
zaimplementowano
3) Zakończyłem moją funkcję, w której muszę wywołać getActivity (), w wątku, ponieważ gdyby działał na wątku głównym, zablokowałbym wątek krokiem 4. i onAttach () nigdy nie zostałby wywołany.
4 w mojej funkcji, w której muszę wywołać getActivity (), używam tego (przed wywołaniem getActivity ())
Jeśli masz jakieś aktualizacje interfejsu użytkownika, pamiętaj, aby uruchomić je w wątku interfejsu użytkownika. Muszę zaktualizować ImgeView, więc zrobiłem:
źródło
Kolejność wywoływania wywołań zwrotnych po zatwierdzeniu ():
Musiałem wykonać pracę, która obejmowała niektóre widoki, więc onAttach () nie działało dla mnie; rozbiło się. Więc przesunąłem część mojego kodu, który ustawiał niektóre parametry w metodzie o nazwie zaraz po commit () (1.), a następnie drugą część kodu, która obsługiwała widok wewnątrz onCreateView () (3.).
źródło
Używam OkHttp i właśnie napotkałem ten problem.
W pierwszej części @thucnguyen był na dobrej drodze .
Niektóre połączenia HTTP były wykonywane nawet po zamknięciu działania (ponieważ wykonanie żądania HTTP może chwilę potrwać). Następnie
HttpCallback
spróbowałem zaktualizować niektóre pola Fragment i dostałemnull
wyjątek przy próbiegetActivity()
.IMO rozwiązaniem jest zapobieganie wywołaniom zwrotnym, gdy fragment nie jest już żywy (i to nie tylko z Okhttp).
Poprawka: Zapobieganie.
Jeśli spojrzysz na cykl życia fragmentu (więcej informacji tutaj ), zauważysz, że istnieją
onAttach(Context context)
ionDetach()
metody. Są one wywoływane, gdy Fragment należy do działania i tuż przed tym, zanim przestaną być.Oznacza to, że możemy zapobiec temu wywołaniu zwrotnemu, kontrolując je w
onDetach
metodzie.źródło
Jak wywołujesz tę funkcję? Jeśli wywołasz to w konstruktorze
Fragment
, zwrócinull
.Wystarczy wywołać,
getActivity()
gdy metodaonCreateView()
zostanie wykonana.źródło
Wykonaj następujące czynności. Myślę, że będzie ci to pomocne.
źródło
Ci, którzy nadal mają problem z onAttach (Aktywność), Właśnie zmieniono na Kontekst -
W większości przypadków wystarczy zapisać kontekst - na przykład, jeśli chcesz wykonać getResources (), możesz to zrobić bezpośrednio z kontekstu. Jeśli nadal musisz włączyć kontekst do działania, zrób to -
Zgodnie z sugestią użytkownika 1868713.
źródło
Możesz użyć onAttach lub jeśli nie chcesz wszędzie włączaćAttach, możesz umieścić metodę, która zwraca ApplicationContext na głównej klasie aplikacji:
Następnie możesz ponownie użyć go w dowolnym miejscu w całym projekcie, w ten sposób:
Daj mi znać, jeśli to nie zadziała.
źródło
Innym dobrym rozwiązaniem byłoby użycie LiveData Androida z architekturą MVVM. Zdefiniowałbyś obiekt LiveData w swoim ViewModel i obserwowałbyś go we fragmencie, a gdy wartość LiveData zostanie zmieniona, powiadomiłby swojego obserwatora (w tym przypadku fragment) tylko wtedy, gdy twój fragment jest w stanie aktywnym, więc zagwarantowanie, że sprawi, że interfejs użytkownika będzie działał, a dostęp do działania będzie możliwy tylko wtedy, gdy fragment będzie w stanie aktywnym. Jest to jedna zaleta związana z LiveData
Oczywiście, kiedy zadawano to pytanie po raz pierwszy, nie było LiveData. Pozostawiam tę odpowiedź tutaj, ponieważ, jak widzę, nadal występuje ten problem i może być komuś pomocny.
źródło
Wywołaj metodę getActivity () wewnątrz metody onActivityCreated ()
źródło