Differenza tra onCreateView e onViewCreated in Fragment


119

Qual è la differenza essenziale tra questi due metodi? Quando creo un TextView, dovrei usarne uno sull'altro per le prestazioni?

Modifica: qual è la differenza da

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

Ho aggiunto una modifica per spiegare la mia confusione. Se un metodo viene subito dopo l'altro, perché ce ne sono due? Non è possibile eseguire tutta la creazione della vista con un unico metodo come sopra?
Smith

7
Se devi cercare su Google e indovinare, probabilmente ci sono metodi con nomi sbagliati.
Balázs Németh

Risposte:


85

Affrontiamo alcuni arresti anomali durante l'inizializzazione della visualizzazione in onCreateView.

Dovresti gonfiare il layout onCreateViewma non inizializzare altre visualizzazioni utilizzando findViewByIdin onCreateView.

Perché a volte la visualizzazione non è inizializzata correttamente. Quindi usa sempre findViewByIdin onViewCreated(quando la vista è completamente creata) e passa anche la vista come parametro.

onViewCreated è assicurarsi che la vista sia completamente creata.

Documentazione Android onViewCreated

Chiamato immediatamente dopo il ritorno di onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle), ma prima che qualsiasi stato salvato sia stato ripristinato nella visualizzazione. Ciò offre alle sottoclassi la possibilità di inizializzarsi una volta che sanno che la loro gerarchia di visualizzazione è stata completamente creata. La gerarchia della vista del frammento non è tuttavia collegata al suo genitore a questo punto.


4
Grazie. Ho anche affrontato questo problema e utilizzato il componente. post(...) metodo per attendere finché non viene mostrato. Probabilmente farà findViewById e altre inizializzazioni in onViewCreated.
CoolMind

22
Da dove veniva citato quel testo? Non sono riuscito a trovarlo nella documentazione ufficiale.
Daniel

Potete per favore pubblicare il riferimento dal sito dello sviluppatore della dichiarazione qui citata?
Namrata Bagerwal

4
Questo non è effettivamente corretto. Puoi trovare una vista in onCreateView, ma solo dopo averla gonfiata e solo dalla vista che hai già gonfiato. Fragment.findViewById () non è sicuro, ma View.findViewById () è sicuro se hai già gonfiato la visualizzazione dei frammenti.
Colintheshots

46

onViewCreatedviene chiamato immediatamente dopo onCreateView(il metodo che inizializzi e crei tutti i tuoi oggetti, incluso il tuo TextView), quindi non è una questione di prestazioni.

Dal sito per sviluppatori:

onViewCreated (Visualizza vista, Bundle savedInstanceState)

Chiamato immediatamente dopo la restituzione di onCreateView (LayoutInflater, ViewGroup, Bundle), ma prima che qualsiasi stato salvato sia stato ripristinato nella visualizzazione. Ciò offre alle sottoclassi la possibilità di inizializzarsi una volta che sanno che la loro gerarchia di visualizzazione è stata completamente creata. La gerarchia della vista del frammento non è tuttavia collegata al suo genitore a questo punto.

Fonte: frammento # onViewCreated


28

È meglio eseguire qualsiasi assegnazione di viste secondarie ai campi in onViewCreated. Questo perché il framework esegue un controllo null automatico per garantire che la gerarchia di visualizzazione del frammento sia stata creata e gonfiata (se si utilizza un file di layout XML) correttamente.

Snippet di codice da: 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);
}

6
separa anche qualsiasi logica di inizializzazione dalla logica di inflazione / creazione della gerarchia di visualizzazione
orangemako

1
Questo è interessante, hai risorse aggiuntive sul motivo per cui questo approccio è migliore? Ciò significa che ogni metodo onCreateView dovrebbe consistere solo in un "return inflater.inflate (R.layout.layout_file, container, false);" e onviewcreated dovrebbe avere tutti i metodi "findViewById"? Quale aumento delle prestazioni crea? Renderebbe le transizioni più veloci?
android_student

Per rispondere alla tua prima domanda, onCreateViewviene utilizzato per creare la gerarchia di visualizzazione del frammento. Ciò può avvenire tramite l'inflazione XML o la creazione dinamica (ovvero, la creazione di viste Java in modo programmatico). Quindi potresti non chiamare inflateaffatto. Ma dovresti restituire una vista genitore se il frammento deve avere un elemento dell'interfaccia utente. Altrimenti torna null.
orangemako

Non c'è affatto un aumento delle prestazioni. Guardando il FragmentManagercodice e frammenta per performCreateView, che chiama onCreateView github.com/android/platform_frameworks_base/blob/… , ti vengono garantite alcune cose per il onViewCreatedcallback del ciclo di vita:
orangemako

1. La gerarchia della vista verrà allegata al contenitore se il frammento è stato aggiunto dinamicamente alla sua attività padre. 2. È possibile eseguire ricerche di visualizzazione in sicurezza senza doversi preoccupare degli NPE. 3. Non ho molta familiarità con le animazioni, ma la transizione dei frammenti sarà già stata avviata (ovvero, inviata alla coda dei messaggi del thread dell'interfaccia utente).
orangemako

13

onCreateViewrestituisce la visualizzazione gonfiata. OnViewCreatedviene chiamato subito dopo onCreateViewe get ha come parametro la visualizzazione gonfiata. Il suo tipo restituito èvoid


1
Ho aggiunto una modifica per spiegare la mia confusione. Se un metodo viene subito dopo l'altro, perché ce ne sono due? Non è possibile eseguire tutta la creazione della vista con un unico metodo come sopra?
Smith

3
onCreateView dovrebbe tornare rapidamente. OnViewCreate può essere utilizzato per eseguire operazioni di inizializzazione, ad esempio. Come ho detto, onViewCreated ha come parametro la View che hai gonfiato all'interno di onCreateView. Quindi puoi evitare la getViewchiamata
Blackbelt

8

onCreateView()è l'equivalente del frammento di onCreate()per le attività e viene eseguito durante la creazione della vista.
onViewCreated()viene eseguito dopo che la vista è stata creata.

should I use one over the other for performance? NO . Non ci sono prove di un aumento delle prestazioni.

In realtà esiste anche un onCreate()metodo in Fragments, ma è usato raramente ( non lo uso mai , né trovo un buon caso d'uso).

Uso sempre onCreateView()in Fragments come sostituto di onCreate().
E ne sono felice.


2
@npace, perché? Penso anche che onCreateViewsia un equivalente di Activity's onCreate.
CoolMind

2
@CoolMind Beh, nPace non è totalmente sbagliato, dato che esiste anche un onCreate()metodo in Framents. Ma non è mai usato (o, almeno, non lo uso mai ). Uso sempre onCreateView()in Fragments come sostituto.
Phantômaxx

1
@Rotwang, sono d'accordo con te! Alcuni tutorial usano onCreate per mettere setHasOptionsMenu (true), ma penso che sarebbe meglio farlo in onCreateView o onViewCreated.
CoolMind

1
@ CoolMind Sono totalmente d'accordo. Forse ho usato le parole sbagliate nella mia risposta.
Phantômaxx

1
@Rotwang, hai detto bene. Quando ho usato i frammenti per la prima volta, non sapevo nemmeno perché onCreate non fosse usato.
CoolMind

4

La documentazione perFragment.onCreateView() ora dice:

Si consiglia di gonfiare solo il layout in questo metodo e spostare la logica che opera sulla visualizzazione restituita su onViewCreated (visualizzazione, pacchetto).

Non c'è bisogno che capiamo perché; dobbiamo solo fare come dice la documentazione, ma sarebbe interessante sapere perché esiste questa raccomandazione. La mia ipotesi migliore è la separazione delle preoccupazioni , ma IMHO questo lo rende un po 'più complicato di quanto deve essere.


Se il motivo è la separazione delle preoccupazioni, perché Activity gonfia il suo layout setContentView()in onCreate()?
Minh Nghĩa,

@ MinhNghĩa Buon punto. La risposta a queste domande potrebbe semplicemente essere che è stato progettato da un programmatore diverso che pensa in modo diverso (i frammenti sono stati introdotti alcuni anni dopo che abbiamo ottenuto Android), ma chi lo sa.
Peppe LG

2

Il motivo principale che utilizzerei onViewCreatedè poiché separa qualsiasi logica di inizializzazione dalla logica di inflazione / creazione della gerarchia di visualizzazione che dovrebbe andare in onViewCreate. Tutte le altre caratteristiche di prestazione hanno lo stesso aspetto.


2

Penso che la differenza principale tra queste sia quando usi kotlin.in onCreateView () ogni volta che vuoi accedere alla visualizzazione nel tuo file xml dovresti usare findViewById ma in onViewCreated puoi semplicemente accedere alla tua vista semplicemente chiamandone l'id .


È proprio vero? Ottengo null per la visualizzazione se utilizzo semplicemente l'id nel codice in entrambi i casi. Devo usare sempre findViewById.
Jim Leask

1
No, non lo è .. oncreate view istanzia la vista, onviewcreated viene chiamato dopo oncreateview e prima che gli stati salvati vengano ripristinati ... è più un problema di temporizzazione nel ciclo di vita del frammento
io_

1

onCreateView viene utilizzato in frammento per creare layout e aumentare la visualizzazione. onViewCreated viene utilizzato per fare riferimento alla vista creata dal metodo sopra. Infine è una buona pratica definire action listener in onActivityCreated.

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.