Unterschied zwischen onCreateView und onViewCreated in Fragment

118

Was ist der wesentliche Unterschied zwischen diesen beiden Methoden? Sollte ich beim Erstellen einer Textansicht eine für die Leistung übereinander verwenden?

Bearbeiten: Was ist der Unterschied zu

onCreateView() {
  root = some view
  View v = new View(some context);
  root.add(v);
  return root;
}


onViewCreated() {
  View v = new View(some context);
  getView().add(v);
}
Schmied
quelle
Ich habe eine Bearbeitung hinzugefügt, um meine Verwirrung zu erklären. Wenn eine Methode direkt nach der anderen kommt, warum gibt es dann zwei? Kann nicht die gesamte Ansichtserstellung mit einer einzigen Methode wie oben durchgeführt werden?
Smith
7
Wenn Sie googeln und raten müssen, gibt es wahrscheinlich schlecht benannte Methoden.
Balázs Németh

Antworten:

85

Wir haben einige Abstürze beim Initialisieren der Ansicht in onCreateView.

Sie sollten Ihr Layout in aufblasen, onCreateViewaber keine anderen Ansichten mit findViewByIdin initialisieren onCreateView.

Weil die Ansicht manchmal nicht richtig initialisiert wird. Verwenden Sie also immer findViewByIdin onViewCreated(wenn die Ansicht vollständig erstellt wurde) und es wird auch die Ansicht als Parameter übergeben.

onViewCreated Stellen Sie sicher, dass die Ansicht vollständig erstellt wurde.

onViewCreated Android-Dokumentation

Wird sofort nach der Rückkehr von onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) aufgerufen , jedoch bevor ein gespeicherter Status in der Ansicht wiederhergestellt wurde. Dies gibt Unterklassen die Möglichkeit, sich selbst zu initialisieren, sobald sie wissen, dass ihre Ansichtshierarchie vollständig erstellt wurde. Die Ansichtshierarchie des Fragments ist jedoch zu diesem Zeitpunkt noch nicht an das übergeordnete Element angehängt.

Zar E Ahmer
quelle
4
Vielen Dank. Ich habe mich auch diesem Problem gestellt und eine Komponente verwendet. post(...) Methode, um zu warten, bis es angezeigt wird. Wahrscheinlich wird findViewById und andere Initialisierung in machen onViewCreated.
CoolMind
22
Woher wurde dieser Text zitiert? Ich konnte es nicht in der offiziellen Dokumentation finden.
Daniel
Können Sie bitte die Referenz der hier zitierten Erklärung von der Entwicklerseite veröffentlichen?
Namrata Bagerwal
4
Das ist eigentlich nicht richtig. Sie können eine Ansicht in onCreateView finden, jedoch erst, nachdem Sie sie aufgeblasen haben, und nur in der Ansicht, die Sie bereits aufgeblasen haben. Fragment.findViewById () ist nicht sicher, aber View.findViewById () ist sicher, wenn Sie die Fragmentansicht bereits aufgeblasen haben.
Colintheshots
46

onViewCreatedwird unmittelbar danach aufgerufen onCreateView(die Methode, mit der Sie alle Ihre Objekte initialisieren und erstellen, einschließlich Ihrer TextView), sodass es nicht um die Leistung geht.

Von der Entwicklerseite:

onViewCreated (Ansichtsansicht, Bundle savedInstanceState)

Wird sofort aufgerufen, nachdem onCreateView (LayoutInflater, ViewGroup, Bundle) zurückgegeben wurde, jedoch bevor ein gespeicherter Status in der Ansicht wiederhergestellt wurde. Dies gibt Unterklassen die Möglichkeit, sich selbst zu initialisieren, sobald sie wissen, dass ihre Ansichtshierarchie vollständig erstellt wurde. Die Ansichtshierarchie des Fragments ist jedoch zu diesem Zeitpunkt noch nicht an das übergeordnete Element angehängt.

Quelle: Fragment # onViewCreated

u3l
quelle
28

Es ist besser, Unteransichten Feldern in zuzuweisen onViewCreated. Dies liegt daran, dass das Framework eine automatische Nullprüfung für Sie durchführt, um sicherzustellen, dass die Ansichtshierarchie Ihres Fragments ordnungsgemäß erstellt und aufgeblasen wurde (wenn eine XML-Layoutdatei verwendet wird).

Code-Snippet von: FragmentManger.java

// This calls onCreateView()
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);

// Null check avoids possible NPEs in onViewCreated
// It's also safe to call getView() during or after onViewCreated()
if (f.mView != null) {
    f.mView.setSaveFromParentEnabled(false);
    if (f.mHidden) f.mView.setVisibility(View.GONE);
    f.onViewCreated(f.mView, f.mSavedFragmentState);
}
Orangemako
quelle
6
Es trennt auch jede Initialisierungslogik von der Inflations- / Erstellungslogik der Ansichtshierarchie
orangemako
1
Das ist interessant. Haben Sie zusätzliche Ressourcen, warum dieser Ansatz besser ist? Bedeutet das, dass jede onCreateView-Methode nur aus einem "return inflater.inflate (R.layout.layout_file, container, false)" bestehen sollte? und onviewcreated sollten alle "findViewById" -Methoden haben? Welchen Leistungsschub schafft dies? Würde es Übergänge schneller machen?
android_student
Zur Beantwortung Ihrer ersten Frage onCreateViewwird die Ansichtshierarchie des Fragments erstellt. Dies kann über XML-Inflation oder dynamische Erstellung erfolgen (dh programmgesteuertes Erstellen von Java-Ansichten). Sie können also überhaupt nicht anrufen inflate. Sie sollten jedoch eine übergeordnete Ansicht zurückgeben, wenn das Fragment ein UI-Element haben muss. Ansonsten kehre zurück null.
Orangemako
Es gibt überhaupt keine Leistungssteigerung. Wenn Sie sich den FragmentManagerund Fragment-Code für performCreateViewonCreateView onViewCreated
ansehen
1. Die Ansichtshierarchie wird an den Container angehängt, wenn das Fragment dynamisch zu seiner übergeordneten Aktivität hinzugefügt wurde. 2. Sie können Lookups sicher anzeigen, ohne sich um NPEs sorgen zu müssen. 3. Ich bin mit Animationen nicht so vertraut, aber der Fragmentübergang wurde bereits gestartet (dh an die UI-Thread-Nachrichtenwarteschlange gesendet).
Orangemako
13

onCreateViewGibt die aufgeblasene Ansicht zurück. OnViewCreatedwird gleich danach aufgerufen onCreateViewund get hat Parameter die aufgeblasene Ansicht. Der Rückgabetyp istvoid

Schwarzer Gürtel
quelle
1
Ich habe eine Bearbeitung hinzugefügt, um meine Verwirrung zu erklären. Wenn eine Methode direkt nach der anderen kommt, warum gibt es dann zwei? Kann nicht die gesamte Ansichtserstellung mit einer einzigen Methode wie oben durchgeführt werden?
Smith
3
onCreateView sollte schnell zurückkehren. OnViewCreate kann zum Beispiel verwendet werden, um Initialisierungsvorgänge durchzuführen. Wie gesagt, onViewCreated hat als Parameter die Ansicht, die Sie in onCreateView aufgeblasen haben. So können Sie den getViewAnruf vermeiden
Blackbelt
8

onCreateView()ist das Fragment-Äquivalent onCreate()für Aktivitäten und wird während der Ansichtserstellung ausgeführt.
onViewCreated()wird ausgeführt, nachdem die Ansicht erstellt wurde.

should I use one over the other for performance? NEIN . Es gibt keine Hinweise auf eine Leistungssteigerung.

Es gibt tatsächlich auch eine onCreate()Methode in Fragmenten, aber sie wird selten verwendet (ich verwende sie nie und finde auch keinen guten Anwendungsfall dafür).

Ich benutze immer onCreateView()in Fragmenten als Ersatz für onCreate().
Und damit bin ich zufrieden.

Phantômaxx
quelle
2
@npace, warum? Ich denke auch, dass onCreateViewdies der Aktivität entspricht onCreate.
CoolMind
2
@CoolMind Nun, nPace ist nicht völlig falsch, da es auch onCreate()in Framents eine Methode gibt. Aber es wird nie benutzt (oder zumindest benutze ich es nie ). Ich benutze immer onCreateView()Fragmente als Ersatz.
Phantômaxx
1
@ Rotwang, stimme dir zu! Einige Tutorials verwenden onCreate, um setHasOptionsMenu (true) zu setzen, aber ich denke, es wäre besser, dies in onCreateView oder onViewCreated zu tun.
CoolMind
1
@ CoolMind Ich stimme vollkommen zu. Vielleicht habe ich in meiner Antwort die falschen Wörter verwendet.
Phantômaxx
1
@ Rotwang, du hast richtig gesagt. Als ich zum ersten Mal Fragmente verwendete, wusste ich auch nicht, warum onCreate nicht verwendet wird.
CoolMind
4

Die DokumentationFragment.onCreateView() sagt vorerst :

Es wird empfohlen, das Layout bei dieser Methode nur aufzublasen und die Logik, die für die zurückgegebene Ansicht ausgeführt wird, nach onViewCreated (Ansicht, Bundle) zu verschieben.

Wir müssen nicht verstehen, warum; Wir müssen nur tun, was in den Dokumenten steht, aber es wäre interessant zu wissen, warum diese Empfehlung existiert. Meine beste Vermutung ist die Trennung von Bedenken , aber meiner Meinung nach macht es das ein bisschen komplizierter als es sein muss.

Peppe LG
quelle
Wenn der Grund in der Trennung der Bedenken liegt, warum bläst die Aktivität dann ihr Layout in setContentView()auf onCreate()?
Minh Nghĩa
@ MinhNghĩa Guter Punkt. Die Antwort auf diese Fragen könnte einfach sein, dass es von einem anderen Programmierer entworfen wurde, der anders dachte (Fragmente wurden einige Jahre nach dem ersten Android eingeführt), aber wer weiß.
Peppe LG
2

Der Hauptgrund, den ich verwenden würde, onViewCreatedist, dass er jede Initialisierungslogik von der Inflations- / Erstellungslogik der Ansichtshierarchie trennt, die in die onViewCreate. Alle anderen Leistungsmerkmale sehen gleich aus.

AmeyaB
quelle
2

Ich denke, der Hauptunterschied zwischen diesen besteht darin, dass Sie kotlin.in onCreateView () jedes Mal verwenden, wenn Sie auf die Ansicht in Ihrer XML-Datei zugreifen möchten. Sie sollten findViewById verwenden, aber in onViewCreated können Sie einfach auf Ihre Ansicht zugreifen, indem Sie einfach die ID davon aufrufen .

Shahriar enayaty
quelle
Ist das wirklich wahr? Ich erhalte null für die Ansicht, wenn ich nur die ID im Code so oder so verwende. Ich muss immer die findViewById verwenden.
Jim Leask
1
Nein, es ist nicht ... oncreate view instanziiert die Ansicht, onviewcreated wird nach oncreateview aufgerufen und bevor gespeicherte Zustände wiederhergestellt werden ... es ist eher ein
Zeitproblem
1

onCreateView wird in Fragmenten verwendet, um ein Layout zu erstellen und die Ansicht aufzublasen. onViewCreated wird verwendet, um auf die mit der obigen Methode erstellte Ansicht zu verweisen. Schließlich empfiehlt es sich, den Aktionslistener in onActivityCreated zu definieren.

Salu Khadka
quelle