Ich habe zwei allgemeine Methoden zum Instanziieren eines neuen Fragments in einer Anwendung gesehen:
Fragment newFragment = new MyFragment();
und
Fragment newFragment = MyFragment.newInstance();
Die zweite Option verwendet eine statische Methode newInstance()
und enthält im Allgemeinen die folgende Methode.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Zuerst dachte ich, der Hauptvorteil sei die Tatsache, dass ich die newInstance () -Methode überladen könnte, um beim Erstellen neuer Instanzen eines Fragments Flexibilität zu bieten - aber ich könnte dies auch tun, indem ich einen überladenen Konstruktor für das Fragment erstelle.
Habe ich etwas verpasst?
Was sind die Vorteile eines Ansatzes gegenüber dem anderen? Oder ist es nur eine gute Übung?
android
android-fragments
Graham Smith
quelle
quelle
Antworten:
Wenn Android beschließt, Ihr Fragment später neu zu erstellen, wird der Konstruktor ohne Argumente Ihres Fragments aufgerufen. Das Überladen des Konstruktors ist also keine Lösung.
Wenn dies gesagt ist, besteht die Möglichkeit, Inhalte an Ihr Fragment zu übergeben, damit sie verfügbar sind, nachdem ein Fragment von Android neu erstellt wurde, darin, ein Bundle an die
setArguments
Methode zu übergeben.Wenn wir beispielsweise eine Ganzzahl an das Fragment übergeben möchten, verwenden wir Folgendes:
Und später im Fragment können
onCreate()
Sie auf diese Ganzzahl zugreifen, indem Sie Folgendes verwenden:Dieses Bundle wird auch dann verfügbar sein, wenn das Fragment irgendwie von Android neu erstellt wurde.
Beachten Sie auch:
setArguments
Kann nur aufgerufen werden, bevor das Fragment an die Aktivität angehängt ist.Dieser Ansatz ist auch in der Android-Entwicklerreferenz dokumentiert: https://developer.android.com/reference/android/app/Fragment.html
quelle
Der einzige Vorteil bei der Verwendung der
newInstance()
, die ich sehe, sind die folgenden:Sie haben eine einzige Stelle, an der alle vom Fragment verwendeten Argumente gebündelt werden können, und Sie müssen den folgenden Code nicht jedes Mal schreiben, wenn Sie ein Fragment instanziieren.
Dies ist eine gute Möglichkeit, anderen Klassen mitzuteilen, welche Argumente voraussichtlich korrekt funktionieren (obwohl Sie in der Lage sein sollten, Fälle zu behandeln, wenn in der Fragmentinstanz keine Argumente gebündelt sind).
Ich gehe davon aus, dass die Verwendung einer Statik
newInstance()
zum Instanziieren eines Fragments eine gute Vorgehensweise ist.quelle
Es gibt auch einen anderen Weg:
quelle
instantiate()
Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Während @yydl einen überzeugenden Grund dafür angibt, warum die
newInstance
Methode besser ist:Es ist immer noch möglich, einen Konstruktor zu verwenden . Um zu sehen, warum dies so ist, müssen wir zuerst sehen, warum die obige Problemumgehung von Android verwendet wird.
Bevor ein Fragment verwendet werden kann, wird eine Instanz benötigt. Android ruft
YourFragment()
(der Konstruktor ohne Argumente ) auf, um eine Instanz des Fragments zu erstellen. Hier wird jeder überladene Konstruktor, den Sie schreiben, ignoriert, da Android nicht wissen kann, welchen Sie verwenden sollen.Während der Lebensdauer einer Aktivität wird das Fragment wie oben erstellt und von Android mehrmals zerstört. Dies bedeutet, dass Daten, die in das Fragmentobjekt selbst eingefügt werden, verloren gehen, sobald das Fragment zerstört wird.
Um dies zu umgehen, fordert Android Sie auf, Daten mit einem
Bundle
(AufrufsetArguments()
) zu speichern , auf den dann zugegriffen werden kannYourFragment
. Argumentebundle
werden von Android geschützt und sind daher garantiert dauerhaft .Eine Möglichkeit, dieses Bundle festzulegen, ist die Verwendung einer statischen
newInstance
Methode:Ein Konstruktor:
kann genau das gleiche tun wie die
newInstance
Methode.Dies würde natürlich fehlschlagen und ist einer der Gründe, warum Android möchte, dass Sie die
newInstance
Methode verwenden:Zur weiteren Erklärung hier die Fragmentklasse von Android:
Beachten Sie, dass Android darum bittet, dass die Argumente nur bei der Erstellung festgelegt werden, und garantiert, dass diese beibehalten werden.
BEARBEITEN : Wie in den Kommentaren von @JHH ausgeführt, stellt Java Ihrem Fragment keinen Standardkonstruktor ohne Argumente zur Verfügung, wenn Sie einen benutzerdefinierten Konstruktor bereitstellen, für den einige Argumente erforderlich sind . Dazu müssten Sie einen Konstruktor ohne Argumente definieren. Dies ist Code, den Sie mit der
newInstance
Factory-Methode vermeiden können .BEARBEITEN : Android erlaubt nicht mehr die Verwendung eines überladenen Konstruktors für Fragmente. Sie müssen die
newInstance
Methode verwenden.quelle
Ich bin nicht einverstanden mit yydi Antwort sagen:
Ich denke, es ist eine Lösung und eine gute, genau aus diesem Grund wurde sie von der Java-Kernsprache entwickelt.
Es ist wahr, dass Android-System Ihre zerstören und neu erstellen kann
Fragment
. So können Sie Folgendes tun:Es ermöglicht Ihnen,
someInt
vongetArguments()
letzterem an zu ziehen , selbst wenn dasFragment
vom System neu erstellt wurde. Dies ist eine elegantere Lösung als derstatic
Konstruktor.Meiner Meinung nach sind
static
Konstruktoren nutzlos und sollten nicht verwendet werden. Sie werden Sie auch einschränken, wenn Sie dies in Zukunft erweiternFragment
und dem Konstruktor weitere Funktionen hinzufügen möchten . Mit demstatic
Konstruktor können Sie dies nicht tun.Aktualisieren:
Android hat eine Inspektion hinzugefügt, die alle nicht standardmäßigen Konstruktoren mit einem Fehler kennzeichnet.
Ich empfehle, es aus den oben genannten Gründen zu deaktivieren.
quelle
Einige Kotlin- Codes:
Und Sie können Argumente damit bekommen:
quelle
Die beste Vorgehensweise zum Instanzieren von Fragmenten mit Argumenten in Android besteht darin, eine statische Factory-Methode in Ihrem Fragment zu haben.
Sie sollten vermeiden, Ihre Felder mit der Instanz eines Fragments festzulegen. Denn wenn das Android-System Ihr Fragment neu erstellt und das System mehr Speicher benötigt, wird das Fragment mithilfe eines Konstruktors ohne Argumente neu erstellt.
Weitere Informationen zu bewährten Methoden zum Instanziieren von Fragmenten mit Argumenten finden Sie hier.
quelle
Aufgrund der Fragen zu Best Practices möchte ich hinzufügen, dass es sehr oft eine gute Idee ist, bei der Arbeit mit einigen REST-Webdiensten einen hybriden Ansatz zum Erstellen von Fragmenten zu verwenden
Wir können keine komplexen Objekte übergeben, z. B. ein Benutzermodell, um ein Benutzerfragment anzuzeigen
Was wir aber tun können, ist,
onCreate
diesen Benutzer einzuchecken ! = Null und wenn nicht - dann bringen Sie ihn aus der Datenschicht, andernfalls - verwenden Sie vorhandene.Auf diese Weise erhalten wir sowohl die Fähigkeit, im Falle einer Fragmentwiederherstellung durch Android durch userId neu zu erstellen, als auch die Schnelligkeit für Benutzeraktionen, sowie die Fähigkeit, Fragmente zu erstellen, indem wir das Objekt selbst oder nur dessen ID gedrückt halten
So etwas gefällt mir:
quelle
User user = /*...*/
Setzen Sie den Benutzer in das Bundle:Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user);
und holen Sie den Benutzer von Argumenten ab:User user = getArguments().getParcelable("some_user");
Das Objekt muss die Paketschnittstelle implementieren. LinkVerwenden Sie diesen Code 100% beheben Sie Ihr Problem
Geben Sie diesen Code in firstFragment ein
Dieses Beispiel sendet boolesche Daten
und in SecendFragment
fröhlicher Code
quelle
Die beste Methode zum Instanziieren des Fragments ist die Verwendung der Standardmethode Fragment.instantiate oder der Factory-Methode zum Instanziieren des Fragments.
Achtung: Erstellen Sie immer einen leeren Konstruktor im Fragment eines anderen, während das Wiederherstellen des Fragmentspeichers eine Laufzeitausnahme auslöst.
quelle
Ich bin in letzter Zeit hier. Aber etwas, von dem ich gerade wusste, dass es dir ein bisschen helfen könnte.
Wenn Sie Java verwenden, gibt es nicht viel zu ändern. Aber für Kotlin-Entwickler gibt es hier einen folgenden Ausschnitt, der Sie zu einem Keller machen kann, auf dem Sie laufen können:
Viel Spaß beim Codieren.
quelle
setArguments()
ist nutzlos. Es bringt nur ein Durcheinander.quelle
onViewCreated
Bereich isoliert sein könnte . Ich denke, es ist praktisch, viele Möglichkeiten, dasselbe zu tun. Es ist auch eine einfache Möglichkeit, nach vom Benutzer vorgenommenen Aktualisierungen zugetArguments
onSaveInstanceState
getArguments
. Was ist mit demonViewCreated
Umfang ... Wir können dort das Statusbündel wiederherstellen. Aber ich ziehe es einfach vor,onCreateView
leicht und schnell zu machen und alle umfangreichen Initialisierungen innerhalb eines zu machen,onActivityCreated
weil ichFragment.getActivity()
manchmal gerne zurückkehren möchtenull
und weilonAttach()
Änderungen in der neuen Version von API 23 vorgenommen wurden.set
undget
Arguments
insaveInstanceState
. Sie tun im Wesentlichen das Gleiche wie "unter der Haube"saveInstanceState
ist "unter der Haube". Und die Verwendung vonArguments
ist eine Verdoppelung der Funktionalität, mit der Sie überprüfen: zuerstArguments
Werte und dannsaveInstanceState
Werte. Weil du essaveInstanceState
irgendwie benutzen musst . Was ist mitArguments
... sie sind nicht notwendig.Ich glaube, ich habe eine viel einfachere Lösung dafür.
quelle