Słów kilka na temat fragmentów w androidzie…
Pamiętam, że gdy zaczynałem swoją przygodę z androidem i dotarłem do tematu fragmentów czułem się lekko zagubiony. „Po co to komu, skoro mogę sobie zrobić równie dobrze drugą aktywność i mieć tam wszystko to co miałbym w fragmencie” - tak sobie wtedy myślałem. Później gdy już zacząłem rozumieć fragmenty, to wszystko chciałem robić na fragmentach - ale tak totalnie wszystko, wszystko. Z perspektywy czasu widzę, że nie była to wcale tak cudowna droga jak na początku mi się wydawało. Trzeba odnaleźć złoty środek między tym co warto zrobić fragmentem, a tym co powinno zostać aktywnością. Kończmy ten wstęp i zaczynajmy.
Czym jest fragment?
Fragment jak sama nazwa wskazuje to „fragment” (czyli kawałek) aktywności - właściwie to widok z logiką przyczepiany do aktywności. To co odróżnia fragment od widoku, to fakt że fragment może posiadać swoją własną logikę. Aktywność może posiadać jednocześnie wiele fragmentów. Zaprezentujęteraz kilka przykładów z fragmentami w różnych kombinacjach. Będę do ich oznaczenia używał 2 kolorów: żółtego oraz zielonego.
Na zamieszczonym wyżej obrazku widzimy aktywność, która posiada jeden fragment (żółty). Jak widać po lewej stronie na górze znajduje się navigation drawer, po kliknięciu na element z jego menu zapewne nastąpi podmiana fragmentu. Jest to w mojej opinii najczęstsze wykorzystanie fragmentu, rozwiązanie to pozwala na szybką i wygodną nawigację po aplikacji. Nie ma tu jednak niczego czego nie bylibyśmy w stanie wykonać bez tworzenia nowej aktywności. Idźmy dalej.
Widzimy teraz sytuację, w której to na ekranie pojawiają się jednocześnie 2 różne fragmenty (żółty oraz zielony). Możesz powiedzieć „No ale po co? Dodatkowe komplikacje tylko…wszystko mógłbym mieć w jednej aktywności.” - w zasadzie masz rację. Możesz wszystko wrzucić do jednej aktywności, ale pomyśl jak „przyjemnie” będzie Ci się wtedy dokonywało zmian w takim klocu po 2, 3 lub 4 miesiącach. Jeden wielki widok, logika zbita na siłę do kupy w jednym miejscu - nadal uważasz, że fajniej będzie mieć to w jednej aktywności? Idź dalej.
A co Ty na to? Masz tutaj 2 identyczne fragmenty (żółty 1 oraz żółty 2). Pewnie powiesz, że mogę sobie przecież zrobić widok i dodać go w po prostu layoucie i wyjdzie na to samo. No w zasadzie tak, ale co z kodem związanym z logiką? Wszystko do aktywności? Chcesz później pracować z takim klocem? Przychodzi mi do głowy jeszcze jedno - skoro one są takie same, to czy nie zduplikujesz kodu? A jeśli nawet nie to co sądzisz powiesz wtedy o jego czytelności i złożoności? Pomyśl też o nazwach zmiennych i pól - bt_power_a, bt_power_b, chyba nie chcesz zrobić tego sobie i swoim kolegom ?Idźmy dalej.
Wow! Czy to fragment nad fragmentem? Tak! To dokładniej fragment żółty nad zielonym, a w realnym życiu najczęściej to po prostu Twój monit, który stworzyłeś dziedzicząc po klasie DialogFragment, która to z kolei dziedziczy po klasie „Fragment”. Powiem więcej, każdy wcześniej pokazany żółty fragment to właśnie ten fragment - w końcu dziedziczy po fragmencie, więc możesz go używać jako zwykły fragment, jak i jako monit z racji takiej, że dziedziczysz po DialogFragmencie.
Co się dzieje z używanymi fragmentami?
To zależy od tego czy odkładasz je na stos czy nie. Jeśli nie to sprawa jest prosta - są niszczone, jeśli tak otwarcie kolejnego fragmentu następuje „nad” obecnym fragmentem. Stos pozwala stworzyć historię odwiedzanych przez użytkownika fragmentów, możesz do tego zaimplementować własną nawigację umożliwiającą wędrowanie po historii po przez naciskanie przycisku „cofnij”.
Cykl życia fragmentu vs cykl życia aktywności
Fragmenty posiadają swój własny cykl życia, jednak z racji tej że są wyświetlane w aktywności to cykl ten jest ściśle powiązany z cyklem życia aktywności - czyli w aktywności poszczególne fragmenty mogą umrzeć, a aktywność dalej będzie żywa, ale odwrotna sytuacja nie może nastąpić. Myślę, że poniższy wykres (pochodzący ze strony Google, z działu o fragmentach) ładnie to wyjaśnia.
Kiedy nie warto używać fragmentów
Na to pytanie nie ma prostej odpowiedzi. To trzeba wyczuć kiedy warto ich używać, a kiedy wprowadzą tylko więcej zamieszania - bo tak się może zdarzyć. Jeśli nie planujesz tworzyć mocno rozbudowanego menu, lub będziesz potrzebował umożliwić innym aplikacją otwarcie Twojej aplikacji na konkretnej aktywności to sens używania fragmentów zanika.
Problem gubienia fragmentów
Gdy pracowałeś z DialogFragmentem zapewne zauważyłeś, że po obrocie ekranu dialog tej przestaje poprawnie reagować na zdarzenia - np. OnClick nie działa. Wynika to z faktu, że klikając w przycisk odnosisz się do niewłaściwego dialogu. Ten który stworzyłeś przed obrotem ekranu przestał już istnieć, w jego miejsce pojawił się nowy. Aby uniknąć sytuacji, w której przestajesz mieć kontrolę nad dialogiem powinieneś używać sensownych tagów (do utworzenia dialogu wymagane jest podanie taga). Umożliwiają one odnalezienie dialogu i ustawienie komunikacji na niego. Wszystko o czym mówię sprowadza się do tej jednej linijki kodu:
val uninstallPackageDialog: UninstallPackageDialog? = fragmentManager!!.findFragmentByTag(UninstallPackageDialog.TAG) as UninstallPackageDialog?
w Javie wyglądałoby to tak:
uninstallPackageDialog = (UninstallPackageDialog) getSupportFragmentManager().findFragmentByTag(UninstallPackageDialog.TAG);
if(uninstallPackageDialog != null){
...
}
Dajcie znać czy Wam się podobało i napiszcie o czym jeszcze chcielibyście poczytać 😉
Specjalnie dla Android.com.pl
Łukasz Bednarczyk