15

w mojej aplikacji używam Activity który posiada jeden Fragment z FragmentTabHost i stąd wszystkie jego karty są nested Fragments.Pierwsze odniesienie do fragmentu z zagnieżdżonych FragmentTabHost

Wewnątrz urządzenia Activity, które posiada Fragment z jego nested Fragment, możemy uzyskać odniesienie do załączonego przy użyciu onAttachedFragment().

Ale jak uzyskać odniesienie do nested Fragment z FragmentTabHost?

Odpowiedz

24

Cóż, odkrywanie kodu źródłowego FragmentTabHost Odkryłem, że po dodaniu karty fragmentów, przypisuje znacznik TabSpec do zagnieżdżonego Fragment.

Więc aby uzyskać odniesienie do niniejszej Fragment powinniśmy zadzwonić

getChildFragmentManager().findFragmentByTag(tabSpecTag)

+1

Czy możesz napisać kod gdzie dokładnie robisz mapowanie, ponieważ zawsze dostaję NullPointerException na mojej referencji – Ravi

+1

@Ravi, dodałem ten kod w moim fragmencie onActivityCreated() tam otrzymałem odnośnik do tego fragmentu – DavyJonesUA

+0

Wywołujesz getChildFragmentManager() na którym obiekcie? – Cozzamara

6

starałem to na chwilę, ale byłem coraz null wrócił z FragmentManager bo próbuje uzyskać dostęp do menedżera w onCreateView() natychmiast po dodaniu.

Here is a good explanation on what happened

Ważne jest również, aby pamiętać, że Fragment wypustki, które nie zostały jeszcze wybrane jeszcze nie istnieją w FragmentManager i tak powróci null również. Obejrzałem to, dzwoniąc pod numer mTabHost.setCurrentTab(index), zanim przejdę do wersji Fragment z FragmentManager. Nie jest bardzo czysty, ale działa.

+0

Cóż, otrzymuję odwołanie do zagnieżdżonego 'Fragment' w' onViewCreated() 'at początek rodzicielskiego cyklu życia Fragmentu, sprawdzanie, czy pakiet 'savedInstanceState' ma wartość null - w tym przypadku wiem, co powinno wyglądać domyślnie' Fragment' i użyję określonego znacznika, w innym przypadku otrzymam wartość 'int' z ten pakiet, który reprezentuje sprawdzoną kartę, którą wcześniej tam zapisałem i używa go do przesyłu do określonej klasy fragmentów. Przypisuję zagnieżdżone odwołanie do karty za pomocą 'OnTabChangeListener' przy użyciu tagu' TabSpec' przekazanego do metody 'onTabChanged()'. –

1

powyższych rozwiązań są również działa, ale mam jeszcze jedno proste rozwiązanie,

@Override 
public void onTabChanged(final String tabId) { 

    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 

      mFragment = getChildFragmentManager().findFragmentByTag("Tagname"); 
     } 
    },1000); 
} 

Tu trzeba wdrożyć FragmentTabHost.onTabChangeListener Zachowaliśmy drugą opóźnienie pobierania fragment z childFragmentManager.

Uwaga: Musisz rzucić mFragment, którego fragmentu użyłeś.

+1

Jedna rzecz, którą widzę przynajmniej jako wadę, polega na tym, że tutaj dokonujesz potencjalnego wycieku pamięci, alokując pamięć dla anonimowego obiektu '' 'Handler'''. Po wywołaniu utrzymuje odniesienie do zewnętrznej klasy około sekundy. Jeśli więc zamkniesz swoją czynność zaraz po zmianie karty, nadal będziesz mieć zwisające odwołanie do niej w pamięci. Powinieneś pomyśleć dwa razy, jeśli wywołasz ten kod w klasie '' 'Activity'''. Co więcej, jeśli użytkownik zdecyduje się na piddle ze swoimi kartami i przesunie je losowo, wówczas zamienisz kolejkę wiadomości na '' 'Runnable''' i nie ma możliwości usunięcia ich z' '' Handler''' –

+0

Zgadzam się z tobą ale chciałbym uzyskać właściwą lokalizację, skąd wywołać tę metodę mFragment = getChildFragmentManager(). findFragmentByTag ("Tagname"); ... To jest kod, w którym znalazłem rozwiązanie. Dziękujemy za głęboki przegląd :) –

1

Znalazłem rozwiązanie, które podoba mi się trochę lepiej, ponieważ nie wymaga wykonania kodu z opóźnieniem (co jest zawsze niepewne, biorąc pod uwagę fragmentację sprzętu Android i różne prędkości procesora).

W swojej metodzie onTabChanged(), zanim spróbujesz znaleźć fragment, wywołaj executePendingTransactions() w menedżerze fragmentów powiązanym z tabHost. Wygląda na to, że niektóre miejsca w kodzie źródłowym FragmentTabHost powinny wywoływać executePendingTransactions(), ale nie mogą tego zrobić.

Działa to za każdym razem, gdy karta zmienia się z jednym wyjątkiem ... pierwsza wybrana karta wciąż zwraca wartość null ... W moim konkretnym przypadku udało mi się inaczej obsłużyć ten wyjątek, wprowadzając kod w onResume.

Mam nadzieję, że to pomoże.