Différence entre onCreateView et onViewCreated dans Fragment

119

Quelle est la différence essentielle entre ces deux méthodes? Lorsque je crée un TextView, dois-je utiliser l'un sur l'autre pour les performances?

Edit: Quelle est la différence de

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);
}
Forgeron
la source
J'ai ajouté une modification pour expliquer ma confusion. Si une méthode vient juste après l'autre, pourquoi y en a-t-il deux? Toute la création de vue ne peut-elle pas être effectuée dans une seule méthode comme ci-dessus?
Smith
7
Si vous devez google et deviner, il y a probablement des méthodes mal nommées.
Balázs Németh

Réponses:

85

Nous sommes confrontés à des plantages lors de l'initialisation de la vue dans onCreateView.

Vous devez gonfler votre mise en page onCreateViewmais ne pas initialiser d'autres vues à l'aide de findViewByIdin onCreateView.

Parce que parfois la vue n'est pas correctement initialisée. Donc, utilisez toujours findViewByIdin onViewCreated(lorsque la vue est entièrement créée) et elle transmet également la vue en paramètre.

onViewCreated est une garantie que la vue est entièrement créée.

Documentation onViewCreated android

Appelé immédiatement après le retour de onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle), mais avant que tout état enregistré ne soit restauré dans la vue. Cela donne aux sous-classes une chance de s'initialiser une fois qu'elles savent que leur hiérarchie de vues a été complètement créée. La hiérarchie de vues du fragment n'est cependant pas attachée à son parent à ce stade.

Zar E Ahmer
la source
4
Merci. J'ai également rencontré ce problème et utilisé un composant. post(...) pour attendre qu'elle soit affichée. Fera probablement findViewById et autre initialisation dans onViewCreated.
CoolMind
22
D'où vient ce texte? Je n'ai pas pu le trouver dans la documentation officielle.
Daniel
Pouvez-vous s'il vous plaît publier la référence du site du développeur de la déclaration citée ici?
Namrata Bagerwal
4
Ce n'est pas vraiment correct. Vous pouvez trouver une vue dans onCreateView, mais seulement après l'avoir gonflée et uniquement à partir de la vue que vous avez déjà gonflée. Fragment.findViewById () n'est pas sûr, mais View.findViewById () est sûr si vous avez déjà gonflé la vue fragmentée.
colintheshots
46

onViewCreatedest appelée immédiatement après onCreateView(la méthode que vous initialisez et créez tous vos objets, y compris le vôtre TextView), donc ce n'est pas une question de performances.

Depuis le site du développeur:

onViewCreated (Vue vue, Bundle savedInstanceState)

Appelé immédiatement après le retour de onCreateView (LayoutInflater, ViewGroup, Bundle), mais avant que tout état enregistré n'ait été restauré dans la vue. Cela donne aux sous-classes une chance de s'initialiser une fois qu'elles savent que leur hiérarchie de vues a été complètement créée. La hiérarchie de vues du fragment n'est cependant pas attachée à son parent à ce stade.

Source: Fragment # onViewCreated

u3l
la source
28

Il est préférable d’affecter des sous-vues à des champs dans onViewCreated. Cela est dû au fait que l'infrastructure effectue une vérification automatique des valeurs nulles pour vous assurer que la hiérarchie de vues de votre fragment a été créée et gonflée correctement (si vous utilisez un fichier de mise en page XML).

Extrait de code de: 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
la source
6
il sépare également toute logique d'initialisation de la logique d'inflation / création de hiérarchie de vue
orangemako
1
C'est intéressant, avez-vous des ressources supplémentaires sur pourquoi cette approche est meilleure? Cela signifie-t-il que chaque méthode onCreateView ne doit être constituée que d'un "return inflater.inflate (R.layout.layout_file, container, false);" et onviewcreated devrait avoir toutes les méthodes "findViewById"? Quelle amélioration de performance cela crée-t-il? Cela rendrait-il les transitions plus rapides?
android_student
Pour répondre à votre première question, onCreateViewsert à créer la hiérarchie de vue du fragment. Cela peut se faire via l'inflation XML ou la création dynamique (c'est-à-dire la création de vues Java par programme). Vous ne pouvez donc pas du tout appeler inflate. Mais vous devez renvoyer une vue parente si le fragment doit avoir un élément d'interface utilisateur. Sinon, retournez null.
orangemako
Il n'y a pas du tout d'augmentation des performances. En regardant le FragmentManagercode et le fragment de performCreateView, qui appelle onCreateView github.com/android/platform_frameworks_base/blob/… , vous avez la garantie de quelques choses pour le onViewCreatedrappel du cycle de vie:
orangemako
1. La hiérarchie de vues sera attachée au conteneur si le fragment a été ajouté dynamiquement à son activité parent. 2. Vous pouvez effectuer des recherches de vues en toute sécurité sans vous soucier des NPE. 3. Je ne suis pas très familier avec les animations, mais la transition de fragment aura déjà été lancée (c'est-à-dire envoyée à la file d'attente des messages du thread de l'interface utilisateur).
orangemako
13

onCreateViewrenvoie la vue gonflée. OnViewCreatedest appelé juste après onCreateViewet get a paramètre la vue gonflée. Son type de retour estvoid

Ceinture noire
la source
1
J'ai ajouté une modification pour expliquer ma confusion. Si une méthode vient juste après l'autre, pourquoi y en a-t-il deux? Toute la création de vue ne peut-elle pas être effectuée dans une seule méthode comme ci-dessus?
Smith
3
onCreateView devrait revenir rapidement. OnViewCreate peut être utilisé pour effectuer des opérations d'initialisation, par exemple. Comme je l'ai dit, onViewCreated a comme paramètre la vue que vous avez gonflée à l'intérieur de onCreateView. Vous pouvez donc éviter l' getViewappel
Blackbelt
8

onCreateView()est l'équivalent Fragment de onCreate()for Activities et s'exécute lors de la création de la vue.
onViewCreated()s'exécute après la création de la vue.

should I use one over the other for performance? NON . Il n'y a aucune preuve d'une amélioration des performances.

Il existe en fait une onCreate()méthode dans Fragments aussi, mais elle est rarement utilisée (je ne l' utilise jamais , ni ne trouve un bon cas d'utilisation).

J'utilise toujours onCreateView()dans Fragments en remplacement de onCreate().
Et j'en suis content.

Phantômaxx
la source
2
@npace, pourquoi? Je pense aussi que onCreateViewc'est l'équivalent de l'activité onCreate.
CoolMind
2
@CoolMind Eh bien, nPace n'est pas totalement faux, puisqu'il existe également une onCreate()méthode dans Framents. Mais il n'est jamais utilisé (ou, du moins, je ne l' utilise jamais ). J'utilise toujours onCreateView()dans Fragments en remplacement.
Phantômaxx
1
@Rotwang, d'accord avec vous! Certains tutoriels utilisent onCreate pour mettre setHasOptionsMenu (true), mais je pense que cela ferait mieux de le faire dans onCreateView ou onViewCreated.
CoolMind
1
@CoolMind Je suis totalement d'accord. Peut-être ai-je utilisé les mauvais mots dans ma réponse.
Phantômaxx
1
@Rotwang, vous avez bien dit. Lorsque j'ai utilisé des fragments pour la première fois, je ne savais pas non plus pourquoi onCreate n'est pas utilisé.
CoolMind
4

La documentation pour l'Fragment.onCreateView() instant dit:

Il est recommandé de gonfler uniquement la disposition dans cette méthode et de déplacer la logique qui opère sur la vue retournée vers onViewCreated (View, Bundle).

Inutile de comprendre pourquoi; nous devons simplement faire ce que dit la documentation, mais il serait intéressant de savoir pourquoi cette recommandation existe. Ma meilleure hypothèse est la séparation des préoccupations , mais à mon humble avis, cela rend les choses un peu plus compliquées qu'il ne le faut.

Peppe LG
la source
Si la raison est la séparation des préoccupations, alors pourquoi l' activité gonflent sa mise en page setContentView()en onCreate()?
Minh Nghĩa le
@ MinhNghĩa Bon point. La réponse à ces questions pourrait simplement être qu'il a été conçu par un programmeur différent pensant différemment (des fragments ont été introduits quelques années après avoir obtenu Android pour la première fois), mais qui sait.
Peppe LG le
2

La raison principale que j'utiliserais onViewCreatedest qu'elle sépare toute logique d'initialisation de la logique d'inflation / création de hiérarchie de vue qui devrait aller dans le onViewCreate. Toutes les autres caractéristiques de performance se ressemblent.

AmeyaB
la source
2

Je pense que la principale différence entre ceux-ci est lorsque vous utilisez kotlin.in onCreateView () chaque fois que vous souhaitez accéder à la vue dans votre fichier xml, vous devez utiliser findViewById, mais dans onViewCreated, vous pouvez simplement accéder à votre vue en appelant simplement son identifiant .

Shahriar enayaty
la source
Est-ce vraiment vrai? J'obtiens null pour la vue si j'utilise simplement l'identifiant dans le code de toute façon. Je dois toujours utiliser le findViewById.
Jim Leask
1
Non, ce n'est pas le cas .. oncreate view instancie la vue, onviewcreated est appelé après oncreateview et avant que les états enregistrés ne soient restaurés ... c'est plus un problème de synchronisation dans le cycle de vie du fragment
me_
1

onCreateView est utilisé dans le fragment pour créer une mise en page et gonfler la vue. onViewCreated est utilisé pour référencer la vue créée par la méthode ci-dessus. Enfin, il est recommandé de définir un écouteur d'action dans onActivityCreated.

Salu Khadka
la source