Wie viele Aktivitäten gegen Fragmente?

185

Intro:

Das grundlegende Muster "Fragment-Tutorial" sieht ungefähr so ​​aus:

  1. Haben Sie auf einem Tablet links eine Liste, rechts Details.
  2. Beide sind Fragmentsund beide wohnen im selbenActivity .
  3. Haben Sie auf einem Telefon eine Liste Fragmentin einerActivity .
  4. Starten Sie eine neue Activitymit den Details Fragment.

(zB Android 3.0 Fragments API von Dianne Hackborn und das Fragments API Guide )

Auf beiden Geräten befindet sich die Funktionalität in der Fragments. (einfach)

Auf dem Tablet ist die gesamte App 1Activity , auf dem Telefon gibt es vieleActivities .


Fragen:

  • Gibt es einen Grund, die Telefon-App in viele zu teilen Activities?

Ein Problem bei dieser Methode besteht darin, dass Sie einen Großteil der Logik im Haupttablett Activityund im separaten Telefon duplizierenActivities .

  • Wäre es nicht einfacher, das 1-Aktivitätsmodell in beiden Fällen beizubehalten Fragmentsund dieselbe Logik für das Ein- und Ausschalten zu verwenden (nur mit einem anderen Layout)?

Auf diese Weise befindet sich der größte Teil der Logik in sich Fragmentsselbst, und es gibt nur eine einzige ActivityDuplizierung von Code.

Auch das, was ich über das lesen ActionBarSherlockist , dass es am besten zu funktionieren mit scheint Fragmentsstatt Activities(aber ich habe nicht mit ihm noch gearbeitet).

Sind die Tutorials zu stark vereinfacht oder habe ich bei diesem Ansatz etwas Wichtiges verpasst?


Wir haben beide Ansätze erfolgreich im Büro ausprobiert - aber ich bin dabei, ein größeres Projekt zu starten und möchte es mir so einfach wie möglich machen.

Einige Links zu verwandten Fragen:


Aktualisierung

Begonnenes Kopfgeld auf Frage - immer noch nicht überzeugt, warum ich meine App-Logik in meiner Tablet-Aktivität und in jeder Telefonaktivität duplizieren muss.

Fand auch einen interessanten Artikel von den Jungs von Square, der es wert ist, gelesen zu werden:

Richard Le Mesurier
quelle
38
+1 für eine großartige und gut geschriebene Frage.
Siddharth Lele
Das schmerzt mich heutzutage sehr. Derzeit arbeite ich an einer Anwendung, deren Design viele Fragmente enthält und die sowohl auf dem Telefon als auch auf dem Tablet verfügbar sein wird. Ich suche nach einem Mittelweg, konnte aber noch keinen finden ...
Nixit Patel
1
Ich meine ehrlich gesagt nichts für ungut, aber ich denke, Sie haben einfach akzeptiert, was Sie hören wollten, und nicht die eigentliche Antwort. Die Antwort von Scuba wird von Google nicht empfohlen und der Blog-Beitrag, den ich gerne erklärte, erklärt warum.
pjco
1
@pjco Insbesondere bin ich nicht damit einverstanden, eine onItemSelected()Methode in der Aktivität zu haben. In meiner "echten" App habe ich viele Listen und Unterlisten. Dieses Muster legt nahe, dass meine Tab-Aktivität eine onItemSelected()Methode zum Behandeln jeder der Listen haben muss. Außerdem muss in den Telefonaktivitäten jeweils dieselbe Logik dupliziert sein. IMHO ist es viel besser, die Item Selected-Logik in jedes Fragment einzufügen - es gibt keine Duplizierung und ich bevorzuge diese Art der Strukturierung des Codes. Ich hoffe das hilft
Richard Le Mesurier
2
Ich bin derzeit bei der Arbeit in dieses Dilemma verwickelt. Fragmente werden viel schneller geladen als das Starten neuer Aktivitäten. Daher habe ich begonnen, eine einzelne Aktivitätsarchitektur zu implementieren. Ich bin jedoch auf ein Problem gestoßen, das heißt, ich kann anscheinend keinen guten Weg finden, um Konfigurationen mit mehreren Fragmenten zu unterstützen, ohne etwas Hackiges zu tun. Siehe diese Frage .
Theblang

Antworten:

41

Ich bin damit einverstanden, dass die Tutorials sehr vereinfacht sind. Sie stellen nur vor, Fragmentsaber ich stimme dem vorgeschlagenen Muster nicht zu.

Ich stimme auch zu, dass es keine gute Idee ist, die Logik Ihrer App über viele Aktivitäten hinweg zu duplizieren (siehe DRY-Prinzip auf Wikipedia ).


Ich bevorzuge das Muster der ActionBarSherlockFragments Demo App ( hier herunterladen und Quellcode hier ). Die Demo, die dem in der Frage erwähnten Tutorial am ehesten entspricht, heißt in der App "Layout". oder FragmentLayoutSupportim Quellcode.

In dieser Demo wurde die Logik aus dem Activityund in den verschoben Fragment. Das TitlesFragmententhält tatsächlich die Logik zum Ändern von Fragmenten. Auf diese Weise ist jede Aktivität sehr einfach. Das Duplizieren vieler sehr einfacher Aktivitäten, bei denen sich keine Logik in den Aktivitäten befindet, macht es sehr einfach.

Wenn Sie die Logik in die Fragmente einfügen, müssen Sie den Code nicht mehr als einmal schreiben . Es ist verfügbar, unabhängig davon, in welche Aktivität das Fragment versetzt wird. Dies macht es zu einem leistungsfähigeren Muster als das im Basis-Tutorial vorgeschlagene.

    /**
    * 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);
        }
    }

Ein weiterer Vorteil des ABS- Musters besteht darin, dass Sie keine Tablet-Aktivität mit viel Logik erhalten, was bedeutet, dass Sie Speicherplatz sparen. Das Tutorial-Muster kann zu einer sehr großen Hauptaktivität in einer komplexeren App führen. da es die Logik aller Fragmente verarbeiten muss, die jederzeit darin platziert werden.

Betrachten Sie es insgesamt nicht als gezwungen, viele Aktivitäten zu nutzen. Stellen Sie sich vor, Sie haben die Möglichkeit, Ihren Code in viele Fragmente aufzuteilen und bei deren Verwendung Speicherplatz zu sparen.

Stephen Asherson
quelle
Vielen Dank für eine umfassende Antwort - Ich habe mir die ABS-Demos angesehen und denke, dass es dort viel guten Code gibt. Ich werde versuchen, stattdessen einen Großteil meiner Logik in die Fragmente zu verlagern
Richard Le Mesurier,
Die Demo-Anwendung wurde hierher verschoben: play.google.com/store/apps/…
Philipp E.
Ich denke, das Muster, das Sie beschreiben, stammt aus dem ursprünglichen Google-Beispielcode: android-developers.blogspot.com/2011/02/… Ich denke, ActionBarSherlock hat gerade den Google-Demo-Code portiert, um ABS-Klassen zu verwenden.
Dan J
17

Ich denke, Sie sind auf dem richtigen Weg. (Und ja, die Tutorials sind zu stark vereinfacht).

In einem Tablet-Layout können Sie eine einzelne Aktivität verwenden und Fragmente ein- und auswechseln (in mehreren "Fenstern"). In einem Telefonlayout können Sie für jedes Fragment eine neue Aktivität verwenden.

Wie so:

Geben Sie hier die Bildbeschreibung ein

Es mag wie viel zusätzliche Arbeit erscheinen, aber durch die Verwendung mehrerer Aktivitäten für Telefone aktivieren Sie den grundlegenden Aktivitätslebenszyklus und das Übergeben von Absichten. Dadurch kann das Framework auch alle Animationen und den Backstack verarbeiten.

Um den Code zu reduzieren, können Sie a verwenden BaseActivityund daraus erweitern.

Wenn der Benutzer also ein Tablet hat, das Sie verwenden würden, MyMultiPaneFragActivityoder ähnliches. Diese Aktivität ist für die Verwaltung von Rückrufen von den Fragmenten und das Weiterleiten von Absichten an das richtige Fragment (z. B. eine Suchabsicht) verantwortlich.

Wenn der Benutzer ein Telefon hat, können Sie eine reguläre Aktivität mit sehr wenig Code verwenden und diese erweitern MyBaseSingleFragActivityoder ähnliches. Diese Aktivitäten können sehr einfach sein, 5-10 Codezeilen (vielleicht sogar weniger).

Der schwierige Teil ist das Weiterleiten von Absichten und so weiter. * (Bearbeiten: siehe unten).

Ich denke, der Grund, warum dies empfohlen wird, besteht darin, Speicherplatz zu sparen und Komplexität und Kopplung zu reduzieren. Wenn Sie Fragmente austauschen, FragmentManagerbehält das einen Verweis auf dieses Fragment für den Backstack bei. Es vereinfacht auch, was für den Benutzer "ausgeführt" werden soll. Dieses Setup entkoppelt auch die Ansichten sowie das Layout und die Logik im Fragment vom Aktivitätslebenszyklus. Auf diese Weise kann ein Fragment in einer einzelnen Aktivität neben einem anderen Fragment (zwei Fenster) oder in einer Aktivität mit drei Fenstern usw. vorhanden sein.

* Einer der Vorteile des regelmäßigen Intent-Routings besteht darin, dass Sie eine Aktivität explizit von einer beliebigen Stelle im Backstack aus starten können. Ein Beispiel könnten Suchergebnisse sein. (MySearchResults.class).

Lesen Sie hier mehr:

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

Es könnte etwas mehr Vorarbeit sein, da jedes Fragment für verschiedene Aktivitäten gut funktionieren muss, aber es zahlt sich normalerweise aus. Dies bedeutet, dass Sie alternative Layoutdateien verwenden können, die verschiedene Fragmentkombinationen definieren, den Fragmentcode modular halten, die Verwaltung von Aktionsleisten vereinfachen und das System die gesamte Arbeit des Backstacks erledigen lassen.

pjco
quelle
Was den Vorteil von MySearchResults betrifft - Sie schlagen vor, je nach Mobilteil oder Tablet unterschiedlich auf diese Absicht zu reagieren - warum ist dies besser als eine einzelne Aktivität, die in beiden Fällen reagiert? Sie schlagen vor, dass es auf dem Tablet kein reguläres Intent-Routing gibt - Sie müssen also das Problem für das Tablet trotzdem lösen. Warum nicht diese Lösung auch auf dem Mobilteil verwenden?
Richard Le Mesurier
Der Vorteil hierbei ist, dass Ihr Tablet-Code voraussichtlich zu mehreren Fenstern weitergeleitet wird. Manchmal möchten Sie mehrere Fenster mit einer einzigen Absicht ändern. Zum Beispiel ein Suchergebnis links mit den Detials des ersten Elements im größeren Bereich rechts. Dieser Code wäre nicht auf ein einzelnes Layout portierbar.
pjco
Warum ist es in Ordnung, Fragmente zu wechseln, wenn es viele gibt, aber wenn nur 1 Fragment sichtbar ist, darf ich nicht zu einem anderen Fragment wechseln?
Richard Le Mesurier
Ich bin mir nicht sicher, was ich meine, aber um meinen obigen Kommentar zu verdeutlichen: Manchmal möchten Sie möglicherweise mehr als ein Fragment gleichzeitig in einem Layout mit mehreren Fragmenten ändern. Dies erfordert Code, um 2 Fragmente zu ändern, die Sie nicht in einem einzelnen Fragmentlayout wiederverwenden würden
pjco
Gern geschehen :) Bitte stimmen Sie zu oder akzeptieren Sie, wenn Sie der Meinung sind, dass die Antwort hilfreich ist
pjco
6

Hier ist die Antwort von Reto Meier, die aus diesem Video des Android Fundamentals-Kurses von Udacity stammt .

Es gibt eine Reihe von Gründen, warum Sie Ihre App besser in verschiedene Aktivitäten aufteilen sollten.

  • Eine einzige monolithische Aktivität erhöht die Komplexität Ihres Codes und erschwert das Lesen, Testen und Verwalten.
  • Erschwert das Erstellen und Verwalten von Absichtsfiltern erheblich.
  • Erhöht das Risiko einer engen Kopplung unabhängiger Komponenten.
  • Erhöht die Wahrscheinlichkeit von Sicherheitsrisiken erheblich, wenn die einzelne Aktivität sowohl vertrauliche als auch sicher zu teilende Informationen enthält.

Eine gute Faustregel ist, eine neue Aktivität zu erstellen, wenn sich der Kontext ändert. Zum Beispiel das Anzeigen einer anderen Art von Daten und das Wechseln von der Anzeige zur Dateneingabe.

Aditya Naique
quelle
Interessanterweise lautet der Titel des Videos "Warum wir nicht nur Fragmente verwenden"
Richard Le Mesurier
Es ist ein guter Ansatz, ich stehe vor Unmengen von Problemen mit einzelnen Aktivitäten, mehreren Fragmenten ... echte
Erfahrung
4

Ein Problem bei dieser Methode besteht darin, dass Sie einen Großteil der Logik in der Hauptaktivität des Tablets und in den separaten Telefonaktivitäten duplizieren.

Im Master-Detail-Muster gibt es zwei Aktivitäten. Man zeigt beide Fragmente auf größeren Bildschirmen und nur das "Master" -Fragment auf kleineren Bildschirmen. Das andere zeigt das "Detail" -Fragment auf kleineren Bildschirmen.

Ihre Detaillogik sollte im Detailfragment verknüpft sein. Daher gibt es keine Codeduplizierung in Bezug auf die Detaillogik zwischen Aktivitäten - die Detailaktivität zeigt lediglich das Detailfragment an und übergibt möglicherweise Daten von einem IntentExtra.

Außerdem habe ich über den ActionBarSherlock gelesen, dass er am besten mit Fragmenten anstelle von Aktivitäten zu funktionieren scheint (aber ich habe noch nicht damit gearbeitet).

ActionBarSherlock hat nicht mehr mit Fragmenten zu tun als die native Aktionsleiste, da ActionBarSherlock lediglich ein Backport der nativen Aktionsleiste ist.

CommonsWare
quelle
Was denken Sie über die Idee einer einzelnen Aktivität?
Theblang
@mattblang: Solange du die richtige Navigation hast, gibt es kein Problem damit.
CommonsWare
1
Ich habe versucht, eine einzelne Aktivitätsarchitektur umzugestalten, da das Ersetzen eines Fragments so viel schneller ist als das Starten einer neuen Aktivität mit demselben Fragment. Ich fühle mich wie in zu viele Tücken leite aber, wie diese . Die meisten Beispiele, die ich online finde, insbesondere für Konfigurationen mit mehreren Fragmenten wie Master-Detail, verwenden keine einzige Aktivität. Ich bin also in einem Dilemma.
Theblang
0

Bezugnehmend auf die erste Frage von "Gibt es einen Grund, die Telefon-App in viele Aktivitäten aufzuteilen?" - Ja. Es kommt einfach auf den verfügbaren Platz an. Ein Tablet bietet Entwicklern mehr Platz und ermöglicht es Entwicklern, mehr auf einen Bildschirm zu bringen. Android sagt uns, dass Aktivitäten einen Bildschirm bereitstellen können . Was Sie also mit einem großen Bildschirm auf einem Tablet tun können, muss möglicherweise auf mehrere Bildschirme eines Telefons verteilt werden, da nicht genügend Platz für alle Fragmente vorhanden ist.

EFlisio
quelle
1. Satz - "Eine Aktivität ist eine Anwendungskomponente, die einen Bildschirm bereitstellt, mit dem Benutzer interagieren können, um etwas zu tun." Ich sehe einen Fehler in meiner ursprünglichen Aussage, ich wollte nicht "sind ein anderer Bildschirm" setzen,
EFlisio