Dilemma: quando usare Frammenti vs Attività:


786

So che Activitiessono progettati per rappresentare una singola schermata della mia applicazione, mentre Fragmentssono progettati per essere riutilizzabili layout dell'interfaccia utente con logica incorporata al loro interno.

Fino a non molto tempo fa, ho sviluppato un'applicazione in quanto diceva che dovevano essere sviluppati. Ho creato un Activityper rappresentare una schermata della mia applicazione e ho usato Frammenti per ViewPagero Google Maps. Raramente ho creato un'interfaccia ListFragmentutente o altra che può essere riutilizzata più volte.

Recentemente sono incappato in un progetto che contiene solo 2 Activitiesuno è un SettingsActivitye l'altro è il MainActivity. Il layout del MainActivityè popolato con molti frammenti nascosti dell'interfaccia utente a schermo intero e ne viene mostrato solo uno. Nella Activitylogica ce ne sono molti FragmentTransitionstra le diverse schermate dell'applicazione.

Quello che mi è piaciuto di questo approccio è che, poiché l'applicazione utilizza un ActionBar, rimane intatta e non si muove con l'animazione di commutazione dello schermo, che è ciò che accade con la Activitycommutazione. Questo dà una sensazione più fluida a quelle transizioni dello schermo.

Quindi suppongo che quello che ti sto chiedendo sia quello di condividere le tue attuali modalità di sviluppo riguardo a questo argomento, so che potrebbe sembrare una domanda basata sull'opinione a prima vista ma la guardo come una domanda di architettura e design Android ... Non proprio una basato sull'opinione.

AGGIORNAMENTO (01.05.2014): A seguito di questa presentazione di Eric Burke di Square , (che devo dire è un'ottima presentazione con molti strumenti utili per gli sviluppatori Android. E non sono in alcun modo correlato a Square)

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

Dalla mia esperienza personale degli ultimi mesi, ho scoperto che il modo migliore per costruire le mie applicazioni è creare gruppi di frammenti che arrivano a rappresentare un flusso nell'applicazione e presentare tutti quei frammenti in uno Activity. Quindi in pratica avrai lo stesso numero di Activitiesnella tua applicazione del numero di flussi. In questo modo la barra delle azioni rimane intatta su tutti gli schermi del flusso, ma viene ricreata cambiando un flusso che ha molto senso. Come afferma Eric Burke e come ho anche capito, la filosofia di usare il minor numero Activitiespossibile non è applicabile a tutte le situazioni perché crea un disastro in quella che chiama l'attività "Dio".


2
Dai un'occhiata al mio post su SO - stackoverflow.com/questions/24647078/…
My God

Risposte:


271

Gli esperti ti diranno: "Quando vedrò l'interfaccia utente, saprò se usare un Activityo un Fragment". All'inizio questo non avrà alcun senso, ma col tempo, sarai in grado di dire se ne hai bisogno Fragmento no.

C'è una buona pratica che ho trovato molto utile per me. Mi è venuto in mente mentre stavo cercando di spiegare qualcosa a mia figlia.

Vale a dire, immagina una scatola che rappresenta uno schermo. Puoi caricare un'altra schermata in questa casella? Se usi una nuova scatola, dovrai copiare più oggetti dalla prima casella? Se la risposta è Sì, allora dovresti usare Fragments, perché la radice Activitypuò contenere tutti gli elementi duplicati per farti risparmiare tempo nel crearli e puoi semplicemente sostituire parti della scatola.

Ma non dimenticare che hai sempre bisogno di un contenitore ( Activity) o le tue parti saranno disperse. Quindi una scatola con parti all'interno.

Fare attenzione a non abusare della scatola. Gli esperti di Android UX consigliano (puoi trovarli su YouTube) quando dovremmo caricarne esplicitamente un altro Activity, invece di utilizzare un Fragment(come quando trattiamo il cassetto di navigazione che ha categorie). Una volta che ti senti a tuo agio Fragments, puoi guardare tutti i loro video. Ancora di più sono materiali obbligatori.

Puoi ora guardare la tua interfaccia utente e capire se hai bisogno di un Activityo un Fragment? Hai avuto una nuova prospettiva? Penso che tu l'abbia fatto.


4
hai un link al feed di YouTube che hai citato? Cerco "Esperti di Android UX" e "Android UX" ma non sono del tutto sicuro di quali video stai parlando.
io--

2
Non più, l'ho guardato più di un anno fa. Cerca un funzionario sviluppatore Android che parla di UX
sandalone il

1
Un esempio di considerazione: l'attività ha parentActivity in modo da poter sintetizzare lo backstack mentre si accede dalla notifica, ma non credo che ci sia tale parentFragment.
fikr4n,


@ToolmakerSteve sì, è getParentFragment, ma non è quello che intendevo amico, vedi developer.android.com/guide/topics/manifest/…
fikr4n

129

La mia filosofia è questa:

Crea un'attività solo se è assolutamente necessario. Con lo stack posteriore reso disponibile per eseguire un sacco di transazioni di frammenti, provo a creare il minor numero possibile di attività nella mia app. Inoltre, comunicare tra i vari frammenti è molto più semplice dell'invio di dati tra attività.

Le transizioni di attività sono costose, giusto? Almeno io lo credo - dal momento che la vecchia attività deve essere distrutta / messa in pausa / interrotta, inserita nello stack e quindi la nuova attività deve essere creata / avviata / ripresa.

È solo la mia filosofia da quando sono stati introdotti i frammenti.


2
vero, ma come hai scritto, a volte è necessario utilizzare le attività. un esempio è uno schermo della fotocamera, dove è meglio usarlo in modalità orizzontale. un altro esempio è la schermata di configurazione che viene mostrata quando si inserisce un appWidget personalizzato (sul "desktop" - l'app di avvio).
sviluppatore Android

Grazie per la risposta e la condivisione della tua esperienza Quindi pensi che sia una buona pratica in Android limitare l'applicazione a un'attività e utilizzare il frammento per tutto lo schermo se l'architettura dell'applicazione lo consente?
Emil Adz,

1
Allora come risolvi il problema dei frammenti che devono passare a vicenda "stato"? Tutto lo stato di tutti i tuoi frammenti deve vivere in un'unica attività, altrimenti sei costretto a usare un singleton.
Mr_E,

36
Non sono convinto che comunicare tra vari frammenti sia molto più semplice piuttosto che inviare dati avanti e indietro tra le attività.
Denny,

3
Almeno, onActivityResult()è più sicuro e più semplice dei callback dei frammenti.
CoolMind

59

Bene, secondo le lezioni di Google (forse qui , non ricordo), dovresti considerare di usare i frammenti ogni volta che è possibile, poiché semplifica la gestione e il controllo del codice.

Tuttavia, penso che in alcuni casi possa diventare troppo complesso, poiché l'attività che ospita i frammenti deve spostarsi / comunicare tra di loro.

Penso che dovresti decidere da solo cosa è meglio per te. Di solito non è così difficile convertire un'attività in un frammento e viceversa.

Ho creato un post su questo dillema qui , se desideri leggerne ancora.


5
Grazie per la risposta e la condivisione della tua esperienza Quindi pensi che sia una buona pratica in Android limitare l'applicazione a un'attività e utilizzare il frammento per tutto lo schermo se l'architettura dell'applicazione lo consente?
Emil Adz,

Dipende dal progetto, ma se diventa troppo complicato per te, puoi anche separare più attività. Non abbiate paura di usare nessuno dei metodi. Potresti anche usarli entrambi. Forse a volte sarebbe troppo difficile usare frammenti invece di attività. Penso che dovresti provare a usare i frammenti, ma non forzarlo ad essere ovunque se si mette troppo sulla tua strada ...
Sviluppatore Android

cosa succede se voglio mantenere intatto questo effetto di ActionBar e tutto il contenuto viene cambiato? È possibile raggiungere questo obiettivo con le attività?
Emil Adz,


27

Perché preferisco il frammento all'attività in TUTTI I CASI.

  • L'attività è costosa. In Frammento, le viste e gli stati delle proprietà sono separati - ogni volta che si trova un frammento backstack, le sue viste saranno distrutte. Quindi puoi impilare molti più frammenti di attività.

  • Backstackmanipolazione. Con FragmentManager, è facile cancellare tutti i frammenti, inserirne più che su frammenti ed ecc. Ma per Activity, sarà un incubo manipolare queste cose.

  • Un ciclo di vita molto prevedibile . Finché l'attività host non viene riciclata. i frammenti nel backstack non verranno riciclati. Quindi è possibile utilizzare FragmentManager::getFragments()per trovare frammenti specifici (non incoraggiati).


Ciao, ho letto la tua recensione sui vantaggi di Frag over Act, hai qualche progetto per mostrare lo stesso nel tuo Github Repo?
Ümañg ßürmån,

24

Da Jetpack , l' app per attività singole è l'architettura preferita. Utile soprattutto con il componente Architecture Architecture .

fonte


Grazie per questo!
Simão Garcia,

1
Ho letto di Jetpack per la prima volta oggi. :) Costruiamo app a singola attività da quando sono stati introdotti i frammenti. La multiattività è molto più complicata.
L'incredibile

1
@TheincredibleJan Hai ragione, l'architettura dell'app Single Activity era una soluzione migliore molto prima di Jetpack
Francis,

12

Secondo me non è molto rilevante. Il fattore chiave da considerare è

  1. con quale frequenza riutilizzerai parti dell'interfaccia utente (ad esempio i menu),
  2. l'app è anche per tablet?

L'uso principale dei frammenti è la creazione di attività multipane, che lo rendono perfetto per le app responsive per tablet / telefono.


Direi che l'uso principale dei frammenti è quello di creare viste personalizzate senza considerarle come viste personalizzate. è quello che succede comunque. Frammenti ci vengono mostrati da Google come un modo pratico per creare app responsive per tablet, in modo da poterli attaccare a diverse attività se lo desideri. un modo per collegare il codice a una vista, più o meno, e farli incollare dove vuoi (senza creare viste personalizzate).
Lassi Kinnunen,

11

Non dimenticare che un'attività è il blocco / componente dell'applicazione che può essere condiviso e avviato tramite Intent! Quindi ogni attività nella tua applicazione dovrebbe risolvere solo un tipo di attività. Se hai solo un compito nella tua applicazione, penso che tu abbia bisogno di una sola attività e molti frammenti, se necessario. Naturalmente puoi riutilizzare i frammenti in attività future che risolvono altri compiti. Questo approccio sarà una chiara e logica separazione dei compiti. E non è necessario mantenere un'attività con parametri di filtro di intenti diversi per diversi set di frammenti. Le attività vengono definite nella fase di progettazione del processo di sviluppo in base ai requisiti.


Nelle nostre applicazioni l'unico tipo di attività è tenere il cassetto di navigazione per inserire i diversi frammenti. :) Perché dovrei lottare con l'intenzione di frammenti? È chiaro e logico mantenere un riferimento statico a una classe di dati "globale" per i dati globali e passare alcuni valori a un metodo di istanza di creazione di un frammento.
L'incredibile

9

C'è molto di più di quello che ti rendi conto, devi ricordare che un'attività avviata non distrugge implicitamente l'attività chiamante. Certo, puoi impostarlo in modo tale che l'utente faccia clic su un pulsante per accedere a una pagina, avviare l'attività di quella pagina e distruggere quella corrente. Ciò causa un sacco di spese generali. La migliore guida che posso darti è:

** Inizia una nuova attività solo se ha senso avere l'attività principale e questa aperta contemporaneamente (pensa a più finestre).

Un ottimo esempio di quando ha senso avere più attività è Google Drive. L'attività principale fornisce un esploratore di file. Quando viene aperto un file, viene avviata una nuova attività per visualizzare quel file. Puoi premere il pulsante delle app recenti che ti permetterà di tornare al browser senza chiudere il documento aperto, quindi forse anche aprire un altro documento in parallelo al primo.


Ri "Inizia una nuova attività solo se ha senso avere l'attività principale e questa aperta contemporaneamente (pensa a più finestre)". Io non la penso così. Questa situazione è ben risolta usando frammenti attach / detachmetodi.
ToolmakerSteve

7

Cosa che ho fatto: usare meno frammenti quando possibile. Sfortunatamente, è possibile in quasi tutti i casi. Quindi, finisco con molti frammenti e un po 'di attività. Alcuni inconvenienti che ho realizzato:

  • ActionBar& Menu: quando 2 frammenti hanno un titolo diverso, menu, che
    sarà difficile da gestire. Es .: quando si aggiunge un nuovo frammento, è possibile modificare il titolo della barra delle azioni, ma quando lo si aprebackstack lì non è possibile ripristinare il vecchio titolo. In questo caso potresti aver bisogno di una barra degli strumenti in ogni frammento, ma lasciami credere, che ti farà passare più tempo.
  • Quando ne abbiamo bisogno startForResult, l'attività ha ma il frammento no.
  • Non hai animazione di transizione per impostazione predefinita

La mia soluzione per questo è usare un'attività per avvolgere un frammento all'interno. Quindi abbiamo barra delle azioni, menu startActivityForResult, animazione separati , ...


1
Punti molto utili, grazie. Puoi chiarire " un'attività per avvolgere un frammento "? Hai creato un'attività separata per ciascun frammento? Se è così, hai bisogno del frammento?
ToolmakerSteve

3
c'è un modo per ripristinare titolo e roba. usare getSupportFragmentManager().addOnBackStackChangedListenerper aggiungere un ascoltatore. ottenere frammento corrente in quell'ascoltatore e quindi impostare titolo e cose.
babay,

4

L'unico grande vantaggio di un'attività fragmenteccessiva è che, il codice utilizzato per il frammento può essere utilizzato per diverse attività. Inoltre , fornisce riutilizzabilità del codice nello sviluppo di applicazioni.


3
Come? Potresti fornire qualche esempio per favore?
sofs1,

1
@ sofs1 La tua domanda non ha molto senso. Qualsiasi codice in un frammento rimane lo stesso, indipendentemente dall'attività che il frammento viene istanziata.
L'incredibile

@TheincredibleJan Ma non potremmo anche dire "Qualsiasi codice in un'attività rimane lo stesso indipendentemente da quale attività viene istanziata la seconda attività."? Non vedo la differenza.
iforce2d

3

utilizzare un'attività per applicazione per fornire la base per l' fragment uso fragmentper lo schermo, fragmentssono di peso ridotto rispetto ai activites frammenti, i frammenti riutilizzabili sono più adatti per app che supportano sia il telefono che il tablet


2

Sei libero di usare uno di quelli.
Fondamentalmente, devi valutare qual è il migliore per la tua app. Pensa a come gestirai il flusso aziendale e a come archiviare / gestire le preferenze dei dati.

Pensa a come i frammenti archiviano i dati della spazzatura. Quando si implementa il frammento, si ha una radice attività da riempire con frammenti. Quindi, se stai cercando di implementare molte attività con troppi frammenti, devi considerare le prestazioni sulla tua app, perché stai manipolando (parla grossolanamente) due cicli di vita del contesto, ricorda la complessità.

Ricorda: dovrei usare i frammenti? Perché non dovrei?

Saluti.


1

Uso i frammenti per una migliore esperienza utente. Ad esempio, se si dispone di un pulsante e si desidera eseguire, diciamo un servizio Web quando si fa clic su di esso, allego un frammento all'attività principale.

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();
}

In questo modo l'utente non dovrà spostarsi in un'altra attività.

E in secondo luogo preferisco i frammenti perché puoi gestirli facilmente durante la rotazione.


Cosa rende quell'esempio un'esperienza utente migliore? Come potranno sapere (o preoccuparsi) che stanno facendo un'attività o un frammento?
iforce2d

1

Dipende da cosa vuoi davvero costruire. Ad esempio navigation drawerusa frammenti. Anche le schede usano fragments. Un'altra buona implementazione, è dove hai un listview. Quando si ruota il telefono e si fa clic su una riga, l'attività viene mostrata nella restante metà dello schermo. Personalmente, io uso fragmentse fragment dialogs, poiché è più professionale. Inoltre vengono gestiti più facilmente in rotazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.