Quante attività vs frammenti?


185

Intro:

Il modello base "Fragments Tutorial" è simile al seguente:

  1. Su un tablet, avere un elenco a sinistra, i dettagli a destra.
  2. Entrambi sono Fragmentsed entrambi risiedono nello stesso Activity.
  3. Su un telefono, avere un elenco Fragmentin uno Activity.
  4. Lancia un nuovo Activitycon i dettagli Fragment.

(ad es. API di frammenti di Android 3.0 di Dianne Hackborn e la Guida dell'API di frammenti )

Su entrambi i dispositivi, la funzionalità è in Fragments. (semplice)

Sul tablet , l'intera app è 1Activity , al telefono ce ne sono molteActivities .


Domande:

  • C'è un motivo per dividere l'app del telefono in molte Activities?

Un problema con questo metodo è la duplicazione della maggior parte della logica nel Tablet principale Activitye nel Telefono separato Activities.

  • Non sarebbe più facile conservare il modello 1 Activity in entrambi i casi, usando la stessa logica di accensione Fragmentse spegnimento (usando solo un layout diverso)?

In questo modo la maggior parte della logica risiede nelle Fragmentsstesse e c'è solo una Activityduplicazione del codice, meno singola .

Inoltre quello che ho letto su ActionBarSherlockè che sembra funzionare meglio Fragmentsinvece di Activities(ma non ho ancora lavorato con esso).

I tutorial sono semplificati eccessivamente o ho perso qualcosa di importante in questo approccio?


Abbiamo provato entrambi gli approcci con successo in ufficio, ma sto per iniziare un progetto più grande e voglio rendere le cose il più facili possibile per me stesso.

Alcuni collegamenti a domande correlate:


aggiornamenti

Ha iniziato la ricompensa in questione - non sono ancora convinto del motivo per cui devo duplicare la logica della mia app nell'attività del tablet e in ogni attività del telefono.

Ho anche trovato un interessante articolo dei ragazzi di Square, che vale la pena leggere:


38
+1 per una domanda fantastica e ben scritta.
Siddharth Lele,

questo è qualcosa che mi fa molto male al giorno d'oggi, al momento sto lavorando a un'applicazione il cui design include molti frammenti e sarà disponibile sia sul telefono che sul tablet, sto cercando una via di mezzo, ma non sono ancora riuscito a trovarne ...
Nixit Patel,

1
Onestamente, non intendo offenderti, ma penso che tu abbia semplicemente accettato ciò che volevi sentire piuttosto che la vera risposta. La risposta di Scuba non è raccomandata da Google e il post sul blog che mi è piaciuto spiegare perché.
pjco,

1
@pjco In particolare non sono d'accordo con il onItemSelected()metodo nell'attività. Nella mia app "reale", ho molte liste ed elenchi. Questo modello suggerisce che la mia attività di tabulazione deve avere un onItemSelected()metodo per gestire ciascuno degli elenchi. Inoltre le attività telefoniche devono avere ciascuna la stessa logica duplicata all'interno di ciascuna di esse. IMHO è molto meglio inserire la logica Item Item in ogni frammento - non c'è duplicazione e preferisco quel modo di strutturare il codice. Spero che questo aiuti
Richard Le Mesurier il

2
Al momento sono bloccato da questo dilemma sul lavoro. I frammenti si caricano molto più rapidamente rispetto all'avvio di nuove attività, quindi ho iniziato a implementare un'architettura a singola attività. Mi sono imbattuto in un problema, ma non riesco a trovare un buon modo per supportare configurazioni multi-frammento senza fare qualcosa di strano. Vedere questa domanda .
theblang

Risposte:


41

Sono d'accordo che i tutorial sono molto semplificati. Presentano solo Fragmentsma non sono d'accordo con il modello come suggerito.

Concordo anche sul fatto che non è una buona idea duplicare la logica della tua app in molte attività (vedi Principio DRY su wikipedia ).


Preferisco il modello utilizzato dall'app ActionBarSherlockDemo Fragments ( scarica qui e il codice sorgente qui ). La demo che si avvicina maggiormente al tutorial menzionato nella domanda è quella chiamata "Layout" nell'app; o FragmentLayoutSupportnel codice sorgente.

In questa demo, la logica è stata spostata da Activitye in Fragment. In TitlesFragmentrealtà contiene la logica per cambiare i frammenti. In questo modo, ogni attività è molto semplice. Duplicare molte attività molto semplici, in cui nessuna logica è all'interno delle attività, lo rende molto semplice.

Mettendo la logica nei frammenti, non è necessario scrivere il codice più di una volta ; è disponibile indipendentemente dall'attività in cui è collocato il frammento. Questo lo rende un modello più potente di quello suggerito dal tutorial di base.

    /**
    * Helper function to show the details of a selected item, either by
    * displaying a fragment in-place in the current UI, or starting a
    * whole new activity in which it is displayed.
    */
    void showDetails(int index)
    {
        mCurCheckPosition = index;

        if (mDualPane)
        {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment) getFragmentManager()
                .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index)
            {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                    .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        }
        else
        {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }

Un altro vantaggio del modello ABS è che non si finisce con un'attività tablet che contiene molta logica e ciò significa che si risparmia memoria. Il modello tutorial può portare a una grande attività principale in un'app più complessa; dal momento che deve gestire la logica di tutti i frammenti che vi vengono inseriti in qualsiasi momento.

Nel complesso, non pensare che sia costretto a usare molte attività. Pensalo come avere l'opportunità di dividere il tuo codice in molti frammenti e di risparmiare memoria quando li usi.


grazie per una risposta esaustiva: ho esaminato le demo di ABS e penso che ci sia un sacco di codice valido lì. Cercherò invece di spostare gran parte della mia logica nei frammenti
Richard Le Mesurier il

Demo Application è stata spostata qui: play.google.com/store/apps/…
Philipp E.

Penso che lo schema che stai descrivendo provenga dal codice di esempio originale di Google: android-developers.blogspot.com/2011/02/… Penso che ActionBarSherlock abbia appena portato il codice demo di Google per utilizzare le classi ABS.
Dan J,

17

Penso che tu sia sulla strada giusta. (E sì, i tutorial sono troppo semplificati).

In un layout tablet, è possibile utilizzare un'unica attività e scambiare dentro e fuori i frammenti (in più "riquadri"). Mentre in un layout di telefono è possibile utilizzare una nuova attività per ciascun frammento.

Così:

inserisci qui la descrizione dell'immagine

Può sembrare molto lavoro extra, ma utilizzando più attività per i telefoni, abiliti il ​​ciclo di vita delle attività di base e il passaggio di intenti. Ciò consente inoltre al framework di gestire tutte le animazioni e il back-stack.

Per aiutare a ridurre il codice, è possibile utilizzare a BaseActivityed estenderlo.

Quindi, se l'utente ha un tablet, useresti MyMultiPaneFragActivityo qualcosa di simile. Questa attività è responsabile della gestione dei callback dai frammenti e degli intenti di routing al frammento corretto (come un intento di ricerca)

Se l'utente ha un telefono, è possibile utilizzare un'attività normale con pochissimo codice e estenderlo MyBaseSingleFragActivityo qualcosa di simile. Queste attività potrebbero essere molto semplici, 5-10 righe di codice (forse anche meno).

La parte difficile è indirizzare gli intenti e quant'altro. * (Modifica: vedi più sotto).

Penso che il motivo per cui questo è il modo consigliato sia quello di risparmiare memoria e ridurre la complessità e l'accoppiamento. Se si scambiano frammenti, FragmentManagermantiene un riferimento a quel frammento per il back-stack. Semplifica anche ciò che dovrebbe essere "in esecuzione" per l'utente. Questa configurazione disaccoppia anche le viste, il layout e la logica nel ciclo di vita Frammento dal Attività. In questo modo un frammento può esistere in una singola attività, accanto a un altro frammento (a due riquadri) o in un'attività a tre riquadri, ecc.

* Uno dei vantaggi di disporre del routing di intenti regolari è che puoi avviare un'attività in modo esplicito da qualsiasi punto dello stack. Un esempio potrebbe essere nel caso dei risultati della ricerca. (MySearchResults.class).

Leggi qui per ulteriori informazioni:

http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html

Potrebbe essere un lavoro un po 'più diretto, perché ogni frammento deve funzionare bene in attività separate, ma di solito paga. Ciò significa che è possibile utilizzare file di layout alternativi che definiscono diverse combinazioni di frammenti, mantenere modulare il codice del frammento, semplificare la gestione della barra delle azioni e consentire al sistema di gestire tutto lo stack posteriore.


Per quanto riguarda il vantaggio di MySearchResults - suggerisci di avere un modo diverso di rispondere a quell'intento a seconda del portatile o del tablet - perché è meglio che avere un'unica attività che risponda in entrambi i casi? Suggerisci che su Tablet non esiste un routing di intenti regolari, quindi devi comunque risolvere il problema per il tablet. Perché non usare quella soluzione anche sul portatile?
Richard Le Mesurier,

Il vantaggio qui è che il codice del tablet può prevedere di instradare verso più riquadri. A volte vorrai cambiare più riquadri con un unico intento. Ad esempio, i risultati di una ricerca a sinistra con i dettagli del primo elemento nel riquadro più grande a destra. Questo codice non sarebbe portatile per un singolo layout.
pjco,

Perché è corretto cambiare frammento quando ce ne sono molti, ma se è visibile solo 1 frammento, non devo passare a un altro frammento?
Richard Le Mesurier,

Non sono sicuro di aver capito cosa intendi, ma per chiarire il mio commento sopra: a volte potresti voler cambiare più di 1 frammento contemporaneamente in un layout multi-frammento. Ciò richiede che il codice cambi 2 frammenti, che non potresti riutilizzare in un singolo layout di frammento
pjco,

Prego :) per favore vota o accetta se ritieni che la risposta sia utile
pjco

6

Ecco la risposta di Reto Meier in merito allo stesso, tratta da questo video del corso Android Fundamentals di Udacity .

Esistono diversi motivi per cui è meglio suddividere l'app in diverse attività.

  • Avere una singola attività monolitica aumenta la complessità del codice, rendendo difficile la lettura, il test e la manutenzione.
  • Rende molto più difficile la creazione e la gestione di filtri di intenti.
  • Aumenta il rischio di accoppiamento stretto di componenti indipendenti.
  • Rende molto più probabile l'introduzione di rischi per la sicurezza se la singola attività include sia informazioni sensibili che informazioni sicure da condividere.

Una buona regola pratica è quella di creare una nuova attività ogni volta che il contesto cambia. Ad esempio, la visualizzazione di un diverso tipo di dati e il passaggio dalla visualizzazione all'immissione dei dati.


è interessante notare che il titolo del video è "Why We Don't Only Use Fragments"
Richard Le Mesurier,

è un buon approccio, sto affrontando tonnellate di problemi con frammenti multipli di singola attività ... molto probabilmente probabilmente
GvSharma

4

Un problema con questo metodo è la duplicazione della maggior parte della logica nell'attività principale del tablet e nelle attività telefoniche separate.

Nel modello master-dettaglio, ci sono due attività. Uno mostra entrambi i frammenti su schermi più grandi e solo il frammento "master" su schermi più piccoli. L'altro mostra il frammento "dettaglio" su schermi più piccoli.

La tua logica di dettaglio dovrebbe essere legata nel frammento di dettaglio. Pertanto, non esiste alcuna duplicazione di codice correlata alla logica di dettaglio tra le attività: l'attività di dettaglio mostra semplicemente il frammento di dettaglio, magari passando i dati da un Intentextra.

Inoltre quello che ho letto su ActionBarSherlock è che sembra funzionare meglio con i frammenti anziché con le attività (ma non ci ho ancora lavorato).

ActionBarSherlock non ha più a che fare con i frammenti della barra delle azioni nativa, poiché ActionBarSherlock è puramente un backport della barra delle azioni nativa.


Cosa ne pensi dell'idea di una singola attività?
theblang

@mattblang: Finché hai la navigazione giusta, non c'è problema.
CommonsWare

1
Ho provato a eseguire il refactoring su una singola architettura di attività perché la sostituzione di un frammento è molto più rapida rispetto all'avvio di una nuova attività con lo stesso frammento al suo interno. Mi sento come se stessi incontrando troppi ostacoli, in questo modo . La maggior parte degli esempi che trovo online, in particolare per configurazioni multi-frammento come master-detail, non usano una singola attività. Quindi sono un po 'in un dilemma.
theblang

0

Riferendosi alla prima domanda di "C'è un motivo per dividere l'app del telefono in molte attività?" - Sì. si riduce semplicemente allo spazio disponibile, un Tablet dà più spazio agli sviluppatori, consentendo così agli sviluppatori di mettere più su uno schermo. Android ci dice che le attività possono fornire uno schermo . Quindi, ciò che puoi fare con 1 grande schermo su un tablet, è qualcosa che potrebbe dover essere distribuito su più schermi su un telefono, perché non c'è abbastanza spazio per tutti i frammenti.


1a frase - "Un'attività è un componente dell'applicazione che fornisce una schermata con la quale gli utenti possono interagire per fare qualcosa". Vedo un errore nella mia dichiarazione originale, non intendevo mettere "sono un'altra schermata",
EFlisio
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.