Dylemat: kiedy używać Fragmentów vs Aktywności:

785

Wiem, że Activitieszostały zaprojektowane tak, aby reprezentować pojedynczy ekran mojej aplikacji, podczas gdy Fragmentszostały zaprojektowane tak, aby były układami interfejsu wielokrotnego użytku z wbudowaną logiką.

Do niedawna opracowałem aplikację, ponieważ mówiono, że należy ją opracować. Stworzyłem an Activityreprezentujący ekran mojej aplikacji i użyłem Fragmentów dla ViewPagerlub Google Maps. Rzadko tworzyłem ListFragmentinterfejs użytkownika, który może być wielokrotnie używany.

Ostatnio natknąłem się na projekt, który zawiera tylko 2 Activitiesjeden jest, SettingsActivitya drugi to MainActivity. Układ MainActivityjest zapełniony wieloma ukrytymi pełnoekranowymi fragmentami interfejsu użytkownika i tylko jeden jest pokazany. W Activitylogice jest wiele FragmentTransitionsróżnych ekranów aplikacji.

Podobało mi się to, że ponieważ aplikacja używa an ActionBar, pozostaje nienaruszona i nie porusza się wraz z animacją przełączania ekranu, co dzieje się z Activityprzełączaniem. Daje to bardziej płynne odczucie przejścia między ekranami.

Myślę więc, że chcę podzielić się twoim obecnym sposobem programowania w tym temacie. Wiem, że na pierwszy rzut oka może to wyglądać na pytanie oparte na opiniach, ale patrzę na to jako na pytanie dotyczące projektowania i architektury Androida ... oparty na opiniach.

AKTUALIZACJA (01.05.2014): Po tej prezentacji Erica Burke z Square (muszę powiedzieć, że jest świetną prezentacją z wieloma przydatnymi narzędziami dla programistów Androida. I nie jestem w żaden sposób związany z Square)

http://www.infoq.com/presentations/Android-Design/

Z mojego osobistego doświadczenia w ciągu ostatnich kilku miesięcy odkryłem, że najlepszym sposobem na zbudowanie moich aplikacji jest tworzenie grup fragmentów, które reprezentują przepływ w aplikacji i prezentują wszystkie te fragmenty w jednym Activity. Zasadniczo będziesz mieć taką samą liczbę Activitiesw aplikacji, jak liczba przepływów. W ten sposób pasek akcji pozostaje nienaruszony na wszystkich ekranach przepływu, ale jest odtwarzany po zmianie przepływu, co ma sens. Jak stwierdza Eric Burke i jak sobie uświadomiłem, filozofia używania jak najmniejszej Activitiesliczby nie ma zastosowania do wszystkich sytuacji, ponieważ powoduje bałagan w tym, co nazywa aktywnością „Boga”.

Emil Adz
źródło

Odpowiedzi:

270

Eksperci powiedzą ci: „Kiedy zobaczę interfejs użytkownika, będę wiedział, czy użyć„ Activityczy Fragment”. Na początku nie będzie to miało sensu, ale z czasem będziesz w stanie stwierdzić, czy potrzebujesz, Fragmentczy nie.

Jest taka dobra praktyka, która jest dla mnie bardzo pomocna. Przyszło mi do głowy, kiedy próbowałem coś wyjaśnić mojej córce.

Wyobraź sobie pole przedstawiające ekran. Czy możesz załadować kolejny ekran w tym polu? Jeśli użyjesz nowego pudełka, czy będziesz musiał skopiować wiele elementów z pierwszego pudełka? Jeśli odpowiedź brzmi Tak, powinieneś użyć Fragments, ponieważ root Activitymoże przechowywać wszystkie zduplikowane elementy, aby zaoszczędzić czas w ich tworzeniu, i możesz po prostu wymienić części pudełka.

Ale nie zapominaj , że zawsze potrzebujesz kontenera ( Activity) lub twoje części zostaną rozproszone. Więc jedno pudełko z częściami w środku.

Uważaj, aby nie nadużywać pudełka. Eksperci od Androida UX doradzają (można je znaleźć na YouTube), kiedy powinniśmy jawnie załadować inny Activity, zamiast tego użyć Fragment(na przykład, gdy mamy do czynienia z szufladą nawigacji, która ma kategorie). Gdy poczujesz się komfortowo Fragments, możesz oglądać wszystkie ich filmy. Co więcej, są to materiały obowiązkowe.

Można teraz spojrzeć na UI i dowiedzieć się, czy potrzebny jest Activityalbo Fragment? Czy masz nową perspektywę? Myślę, że tak.

sandalone
źródło
4
czy masz link do wspomnianego kanału na youtube? Poszukuję „ekspertów Android UX” i „Android UX”, ale nie jestem do końca pewien, o których filmach mówisz.
ja--
2
Już nie, oglądałem to ponad rok temu. Wyszukaj oficjalnego autora Androida, który mówi o UX
sandalone
1
Jeden przykład rozważań: aktywność ma parentActivity, dzięki czemu możemy zsyntetyzować backstacka podczas wchodzenia z powiadomienia, ale nie sądzę, aby istniał taki rodzicFragment.
fikr4n
@BornToCode jest getParentFragment: developer.android.com/reference/android/support/v4/app/…
ToolmakerSteve
@ToolmakerSteve tak, to getParentFragment, ale to nie to, co miałem na myśli, stary, patrz developer.android.com/guide/topics/manifest/...
fikr4n
129

Moja filozofia jest następująca:

Utwórz działanie tylko wtedy, gdy jest to absolutnie wymagane. Po udostępnieniu tylnego stosu do zatwierdzania wielu transakcji fragmentarycznych staram się tworzyć jak najmniej działań w mojej aplikacji. Ponadto komunikacja między różnymi fragmentami jest znacznie łatwiejsza niż przesyłanie danych tam iz powrotem między czynnościami.

Przejścia aktywności są drogie, prawda? Przynajmniej tak mi się wydaje - ponieważ stara aktywność musi zostać zniszczona / wstrzymana / zatrzymana, wypchnięta na stos, a następnie nowa aktywność musi zostać utworzona / uruchomiona / wznowiona.

To tylko moja filozofia, odkąd zostały wprowadzone fragmenty.

VJ Vélan Solutions
źródło
2
to prawda, ale jak napisałeś, czasem trzeba korzystać z działań. jednym z przykładów jest ekran aparatu, na którym lepiej jest go używać w trybie poziomym. innym przykładem jest ekran konfiguracji wyświetlany po umieszczeniu niestandardowego widżetu app (na „pulpicie” - aplikacji uruchamiającej).
programista Androida
Dziękujemy za odpowiedzi i dzielenie się doświadczeniami. Więc uważasz, że dobrą praktyką w Androidzie jest ograniczenie aplikacji do jednej Aktywności i użycie Fragmentu na całym ekranie, jeśli architektura aplikacji na to pozwala?
Emil Adz
1
Jak więc rozwiązać problem fragmentów, które muszą przejść przez „stan”? Cały stan we wszystkich twoich fragmentach musi żyć w jednym działaniu, w przeciwnym razie będziesz zmuszony użyć singletona.
Mr_E,
36
Nie jestem przekonany, że komunikacja między różnymi fragmentami jest znacznie łatwiejsza niż przesyłanie danych tam iz powrotem między czynnościami.
Denny
3
Przynajmniej onActivityResult()jest bezpieczniejszy i łatwiejszy niż wywołania zwrotne fragmentów.
CoolMind,
59

Cóż, zgodnie z wykładami Google (być może tutaj , nie pamiętam), powinieneś rozważyć użycie Fragmentów, gdy tylko jest to możliwe, ponieważ ułatwia to utrzymanie i kontrolę kodu.

Myślę jednak, że w niektórych przypadkach może stać się zbyt skomplikowany, ponieważ działanie, które obsługuje fragmenty, wymaga nawigacji / komunikacji między nimi.

Myślę, że powinieneś sam zdecydować, co jest dla ciebie najlepsze. Zazwyczaj konwersja działania na fragment i odwrotnie jest trudna.

Utworzyłem post o tym dillema tutaj , jeśli chcesz przeczytać trochę dalej.

programista Androida
źródło
5
Dziękujemy za odpowiedzi i dzielenie się doświadczeniami. Więc uważasz, że dobrą praktyką w Androidzie jest ograniczenie aplikacji do jednej Aktywności i użycie Fragmentu na całym ekranie, jeśli architektura aplikacji na to pozwala?
Emil Adz
To zależy od projektu, ale jeśli stanie się dla ciebie zbyt skomplikowany, możesz rozdzielić go na wiele działań. Nie bój się użyć żadnej z metod. Możesz także użyć ich obu. Może czasem byłoby ci trudno używać fragmentów zamiast czynności. Myślę, że powinieneś spróbować użyć fragmentów, ale nie zmuszaj go, aby był wszędzie, jeśli staje się zbyt duży na twojej drodze ...
Android deweloper
co jeśli chcę zachować ten wpływ, że ActionBar pozostanie nienaruszony, a cała zawartość zostanie zmieniona? Czy można to osiągnąć za pomocą działań?
Emil Adz,
27

Dlaczego wolę fragment we wszystkich przypadkach.

  • Aktywność jest droga. W Fragmentie widoki i stany właściwości są oddzielone - za każdym razem, gdy fragment jest w środku backstack, jego widoki zostaną zniszczone. Dzięki temu możesz kumulować o wiele więcej Fragmentów niż Aktywność.

  • Backstackmanipulacja. Dzięki FragmentManagerłatwo jest usunąć wszystkie fragmenty, wstawić więcej niż na fragmentach itp. Ale dla Activity manipulowanie tymi rzeczami będzie koszmarem.

  • Bardzo przewidywalny cykl życia . Dopóki aktywność gospodarza nie jest poddawana recyklingowi Fragmenty z plecaka nie zostaną poddane recyklingowi. Można więc użyć FragmentManager::getFragments()do znalezienia określonego Fragmentu (nie zachęca się).

Qylin
źródło
Cześć, Czytałem twoją recenzję o zaletach Frag nad Act, czy masz jakiś projekt, aby pokazać to samo w swoim Github Repo?
Ümañg ßürmån
24

Od Jetpack , aplikacja Single-aktywny jest preferowanym architektura. Przydatne zwłaszcza w przypadku komponentu architektury nawigacji .

źródło

Francis
źródło
Dziękuję Ci za to!
Simão Garcia
1
Po raz pierwszy przeczytałem o Jetpack. :) Budujemy aplikacje do pojedynczej aktywności od czasu wprowadzenia fragmentów. Wiele działań jest znacznie bardziej skomplikowane.
Niesamowity
1
@TheincredibleJan Masz rację, architektura aplikacji Single Activity była lepszym rozwiązaniem na długo przed Jetpack
Francis
12

Moim zdaniem nie ma to większego znaczenia. Kluczowym czynnikiem do rozważenia jest

  1. jak często zamierzasz ponownie używać części interfejsu użytkownika (na przykład menu),
  2. czy aplikacja jest również dostępna na tablety?

Głównym zastosowaniem fragmentów jest budowanie działań wielopłaszczyznowych, co czyni go idealnym dla aplikacji reagujących na tablety / telefony.

Izaak Urbina
źródło
Powiedziałbym, że głównym zastosowaniem fragmentów jest tworzenie niestandardowych widoków bez myślenia o nich jako widokach niestandardowych. tak się dzieje. Fragmenty, które pierwotnie pokazaliśmy od Google, to przydatny sposób tworzenia aplikacji reagujących na tablety, abyś mógł je dowolnie wykonywać w różnych działaniach. sposób na dołączenie kodu do widoku, mniej więcej, i umożliwienie jego kliknięcia w dowolnym miejscu (bez tworzenia niestandardowych widoków).
Lassi Kinnunen
11

Nie zapominaj, że działanie jest blokiem / komponentem aplikacji, który można udostępniać i uruchamiać za pośrednictwem aplikacji Intent! Dlatego każde działanie w Twojej aplikacji powinno rozwiązać tylko jeden rodzaj zadania. Jeśli masz tylko jedno zadanie w swojej aplikacji, myślę, że potrzebujesz tylko jednego działania i wielu fragmentów w razie potrzeby. Oczywiście możesz ponownie wykorzystać fragmenty w przyszłych działaniach, które rozwiązują inne zadania. Takie podejście będzie jasne i logiczne rozdzielenie zadań. I nie ma potrzeby utrzymywania jednej aktywności z różnymi parametrami filtrów intencji dla różnych zestawów fragmentów. Zdefiniuj zadania na etapie projektowania procesu programowania w oparciu o wymagania.

Gość
źródło
W naszych aplikacjach jedynym rodzajem zadania jest przytrzymanie szuflady nawigacji w celu wprowadzenia różnych fragmentów. :) Dlaczego powinienem zmagać się z zamiarami dla fragmentów? Jasne i logiczne jest przechowywanie statycznego odwołania do „globalnej” klasy danych dla danych globalnych i przekazywanie niektórych wartości do metody tworzenia instancji fragmentu.
Niesamowity
9

Jest to coś więcej niż zdajesz sobie sprawę, musisz pamiętać, że uruchomione działanie nie zniszczy pośrednio działania wywołującego. Jasne, możesz ustawić go tak, aby użytkownik kliknął przycisk, aby przejść do strony, rozpocząć aktywność tej strony i zniszczyć bieżącą. Powoduje to duże koszty ogólne. Najlepszy przewodnik, jaki mogę ci dać, to:

** Rozpocznij nową aktywność tylko wtedy, gdy ma sens jednoczesne otwieranie głównej aktywności (ta dotyczy wielu okien).

Świetnym przykładem tego, kiedy sensowne jest prowadzenie wielu działań, to Dysk Google. Główną działalnością jest eksplorator plików. Po otwarciu pliku uruchamiane jest nowe działanie, aby wyświetlić ten plik. Możesz nacisnąć przycisk ostatnich aplikacji, który pozwoli ci wrócić do przeglądarki bez zamykania otwartego dokumentu, a może nawet otworzyć inny dokument równolegle do pierwszego.

TheHebrewHammer
źródło
Odp. „Rozpocznij nową aktywność tylko wtedy, gdy sensowne jest jednoczesne otwarcie głównej i tej aktywności (pomyśl o wielu oknach”). Nie wydaje mi się Ta sytuacja jest dobrze rozwiązana za pomocą fragmentów attach / detachmetod.
ToolmakerSteve
7

Rzecz, którą zrobiłem: używając mniej fragmentu, jeśli to możliwe. Niestety jest to prawie możliwe. Skończyło się na tym, że mam wiele fragmentów i trochę działań. Niektóre wady, które zauważyłem:

  • ActionBar& Menu: gdy 2 fragment ma inny tytuł, menu, które
    będzie trudne w obsłudze. Np .: podczas dodawania nowego fragmentu możesz zmienić tytuł paska akcji, ale kiedy go wyskoczysz, backstacknie ma możliwości przywrócenia starego tytułu. W tym przypadku możesz potrzebować paska narzędzi w każdym fragmencie, ale uwierz mi, że poświęci ci to więcej czasu.
  • Kiedy potrzebujemy startForResult, aktywność ma, ale fragment nie.
  • Domyślnie nie ma animacji przejścia

Moim rozwiązaniem jest użycie działania do zawinięcia fragmentu. Mamy więc osobny pasek akcji, menu startActivityForResult, animację, ...

I Love Coding
źródło
1
Bardzo przydatne punkty, dzięki. Czy możesz wyjaśnić „ działanie polegające na zawinięciu fragmentu ”? Czy stworzyłeś osobną Aktywność dla każdego fragmentu? Jeśli tak, czy w ogóle potrzebujesz Fragmentu?
ToolmakerSteve
3
istnieje sposób na przywrócenie tytułu i innych rzeczy. użyj, getSupportFragmentManager().addOnBackStackChangedListeneraby dodać detektor. pobierz bieżący fragment w tym detektorze, a następnie ustaw tytuł i inne rzeczy.
babay
4

Jedną wielką zaletą fragmentnad działaniem jest to, że kod użyty do fragmentu może być użyty do różnych działań, więc zapewnia możliwość ponownego wykorzystania kodu w rozwoju aplikacji.

Sanchit Bhasin
źródło
3
W jaki sposób? Czy możesz podać jakiś przykład?
sofs1
1
@ sofs1 Twoje pytanie nie ma większego sensu. Każdy kod we fragmencie pozostaje taki sam bez względu na to, z której aktywności fragment jest inicjowany.
Niesamowity
@TheincredibleJan Ale czy nie możemy również powiedzieć „Każdy kod w działaniu pozostaje taki sam, bez względu na to, z którego działania tworzona jest druga aktywność”. Nie widzę różnicy.
iforce2d
3

używać jednej aktywności na stosowanie w celu zapewnienia podstawy do fragment stosowania fragmentna ekranie, fragmentsto masa lite w stosunku do activites części są wielokrotnego użytku fragmentów lepiej dostosowane do aplikacji, które obsługują zarówno telefon i tabletkę

varg
źródło
2

Możesz użyć jednego z nich.
Zasadniczo musisz ocenić, który jest najlepszy dla Twojej aplikacji. Pomyśl o tym, jak będziesz zarządzać przepływem biznesu i jak przechowywać / zarządzać preferencjami danych.

Pomyśl, jak Fragmenty przechowują dane śmieci. Po wdrożeniu fragmentu użytkownik ma główny katalog aktywności do wypełnienia fragmentem (fragmentami). Tak więc, jeśli próbujesz wdrożyć wiele działań ze zbyt dużą ilością fragmentów, musisz wziąć pod uwagę wydajność swojej aplikacji, ponieważ manipulujesz (grubo mówiąc) dwoma cyklami życia kontekstu, pamiętaj o złożoności.

Pamiętaj: czy powinienem używać fragmentów? Dlaczego nie powinienem?

pozdrowienia.

Franklin Hirata
źródło
1

Używam Fragmentów dla lepszego doświadczenia użytkownika. Na przykład, jeśli masz przycisk i chcesz uruchomić, powiedzmy usługę internetową po kliknięciu, dołączam fragment do działania nadrzędnego.

if (id == R.id.forecast) {

    ForecastFragment forecastFragment = new ForecastFragment();
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.main_content, forecastFragment);
    ft.addToBackStack("backstack");
    forecastFragment.setArguments(b);
    ft.commit();
}

W ten sposób użytkownik nie będzie musiał wykonywać innej czynności.

Po drugie, wolę Fragmenty, ponieważ można je łatwo obsługiwać podczas rotacji.

Theo
źródło
Co czyni ten przykład lepszym doświadczeniem użytkownika? Skąd będą wiedzieć (lub przejmować się), że wykonują czynność lub fragment?
iforce2d
1

To zależy od tego, co naprawdę chcesz zbudować. Na przykład navigation drawerwykorzystuje fragmenty. Używaj fragmentsrównież kart . Inną dobrą implementacją jest miejsce, w którym masz listview. Po obróceniu telefonu i kliknięciu wiersza aktywność jest wyświetlana na pozostałej połowie ekranu. Osobiście używam fragmentsi fragment dialogs, ponieważ jest bardziej profesjonalny. Ponadto są obsługiwane łatwiej w rotacji.

Theo
źródło