Diferencia entre onCreateView y onViewCreated en Fragmento

118

¿Cuál es la diferencia esencial entre estos dos métodos? Cuando creo un TextView, ¿debo usar uno sobre el otro para el rendimiento?

Editar: ¿Cuál es la diferencia 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);
}
Herrero
fuente
Agregué una edición para explicar mi confusión. Si un método viene inmediatamente después del otro, ¿por qué hay dos? ¿No se puede realizar toda la creación de vistas con un solo método como el anterior?
Smith
7
Si tiene que buscar en Google y adivinar, probablemente haya métodos mal nombrados.
Balázs Németh

Respuestas:

85

Nos enfrentamos a algunos bloqueos al inicializar la vista en onCreateView.

Debe inflar su diseño, onCreateViewpero no debe inicializar otras vistas usando findViewByIdin onCreateView.

Porque a veces la vista no se inicializa correctamente. Por lo tanto, use siempre findViewByIden onViewCreated(cuando la vista esté completamente creada) y también pasa la vista como parámetro.

onViewCreated es asegurarse de que la vista se haya creado por completo.

Documentación de Android onViewCreated

Se llama inmediatamente después de que onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) haya regresado, pero antes de que se haya restaurado cualquier estado guardado en la vista. Esto les da a las subclases la oportunidad de inicializarse una vez que saben que su jerarquía de vista se ha creado por completo. Sin embargo, la jerarquía de vistas del fragmento no está vinculada a su padre en este punto.

Zar E Ahmer
fuente
4
Gracias. También enfrenté este problema y utilicé el componente. post(...) método para esperar hasta que se muestre. Probablemente hará findViewById y otra inicialización en onViewCreated.
CoolMind
22
¿De dónde fue citado ese texto? No pude encontrarlo en la documentación oficial.
Daniel
¿Puede publicar la referencia del sitio para desarrolladores de la declaración que se cita aquí?
Namrata Bagerwal
4
En realidad, esto no es correcto. Puede encontrar una vista en onCreateView, pero solo después de haberla inflado y solo desde la vista que ya infló. Fragment.findViewById () no es seguro, pero View.findViewById () es seguro si ya ha inflado la vista del fragmento.
colintheshots
46

onViewCreatedse llama inmediatamente después onCreateView(el método que inicializa y crea todos sus objetos, incluido suTextView ), por lo que no es una cuestión de rendimiento.

Desde el sitio del desarrollador:

onViewCreated (Vista de vista, Paquete guardadoInstanceState)

Se llama inmediatamente después de que onCreateView (LayoutInflater, ViewGroup, Bundle) haya regresado, pero antes de que se haya restaurado cualquier estado guardado en la vista. Esto les da a las subclases la oportunidad de inicializarse una vez que saben que su jerarquía de vista se ha creado por completo. Sin embargo, la jerarquía de vistas del fragmento no está vinculada a su padre en este punto.

Fuente: Fragmento # onViewCreated

u3l
fuente
28

Es mejor realizar cualquier asignación de subvistas a campos en onViewCreated. Esto se debe a que el marco realiza una verificación automática de nulos para asegurarse de que la jerarquía de vistas de su Fragmento se haya creado e inflado (si usa un archivo de diseño XML) correctamente.

Fragmento de código 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
fuente
6
también separa cualquier lógica de inicialización de la lógica de creación / inflación de la jerarquía de vista
orangemako
1
Esto es interesante, ¿tiene algún recurso adicional sobre por qué este enfoque es mejor? ¿Eso significa que cada método onCreateView solo debe consistir en un "return inflater.inflate (R.layout.layout_file, container, false);" y onviewcreated debería tener todos los métodos "findViewById"? ¿Qué impulso de rendimiento crea esto? ¿Haría las transiciones más rápidas?
android_student
Para responder a su primera pregunta, onCreateViewse utiliza para crear la jerarquía de vistas del fragmento. Esto puede ser mediante la inflación de XML o la creación dinámica (es decir, creando vistas de Java mediante programación). Así que no puede llamar inflateen absoluto. Pero debe devolver alguna vista principal si el fragmento necesita tener un elemento de IU. De lo contrario, regrese null.
orangemako
No hay ningún aumento de rendimiento en absoluto. Mirando el FragmentManagercódigo y fragmento de performCreateView, que llama a onCreateView github.com/android/platform_frameworks_base/blob/… , se le garantizan algunas cosas para la onViewCreateddevolución de llamada del ciclo de vida:
orangemako
1. La jerarquía de vistas se adjuntará al contenedor si el fragmento se ha agregado dinámicamente a su actividad principal. 2. Puede ver búsquedas de forma segura sin preocuparse por las NPE. 3. No estoy tan familiarizado con las animaciones, pero la transición del fragmento ya se habrá iniciado (es decir, se habrá enviado a la cola de mensajes del hilo de la interfaz de usuario).
orangemako
13

onCreateViewdevuelve la vista inflada. OnViewCreatedse llama justo después onCreateViewy get tiene el parámetro de la vista inflada. Su tipo de retorno esvoid

Cinta negra
fuente
1
Agregué una edición para explicar mi confusión. Si un método viene inmediatamente después del otro, ¿por qué hay dos? ¿No se puede realizar toda la creación de vistas con un solo método como el anterior?
Smith
3
onCreateView debería regresar rápidamente. OnViewCreate se puede utilizar para realizar tareas de inicialización, por ejemplo. Como dije, onViewCreated tiene como parámetro la Vista que inflaste dentro de onCreateView. Para que pueda evitar la getViewllamada
Blackbelt
8

onCreateView()es el Fragmento equivalente de onCreate()para Actividades y se ejecuta durante la creación de la Vista.
onViewCreated()se ejecuta después de que se haya creado la vista.

should I use one over the other for performance? NO . No hay evidencia de un aumento de rendimiento.

En realidad, también hay un onCreate()método en Fragments, pero rara vez se usa ( nunca lo uso, ni le encuentro un buen caso de uso).

Siempre utilizo onCreateView()Fragments como reemplazo de onCreate().
Y estoy feliz con eso.

Phantômaxx
fuente
2
@npace, ¿por qué? También creo que onCreateViewes un equivalente de Activity onCreate.
CoolMind
2
@CoolMind Bueno, nPace no está totalmente equivocado, ya que también hay un onCreate()método en Framents. Pero nunca se usa (o, al menos, yo nunca lo uso). Siempre utilizo onCreateView()Fragments como reemplazo.
Phantômaxx
1
@Rotwang, ¡de acuerdo contigo! Algunos tutoriales usan onCreate para poner setHasOptionsMenu (verdadero), pero creo que sería mejor hacerlo en onCreateView o onViewCreated.
CoolMind
1
@CoolMind Estoy totalmente de acuerdo. Quizás utilicé las palabras equivocadas en mi respuesta.
Phantômaxx
1
@Rotwang, dijiste bien. Cuando usé fragmentos por primera vez, tampoco sabía por qué no se usa onCreate.
CoolMind
4

Los documentos porFragment.onCreateView() ahora dicen:

Se recomienda solo inflar el diseño en este método y mover la lógica que opera en la Vista devuelta a onViewCreated (Vista, Paquete).

No es necesario que entendamos por qué; solo tenemos que hacer lo que dice la documentación, pero sería interesante saber por qué existe esta recomendación. Mi mejor suposición es la separación de preocupaciones , pero en mi humilde opinión, esto lo hace un poco más complicado de lo que debería ser.

Peppe LG
fuente
Si la razón es la separación de preocupación, entonces ¿por qué inflar la actividad en su trazado setContentView()en onCreate()?
Minh Nghĩa
@ MinhNghĩa Buen punto. La respuesta a esas preguntas podría ser simplemente que fue diseñado por un programador diferente que pensaba de manera diferente (los fragmentos se introdujeron algunos años después de que obtuvimos Android por primera vez), pero quién sabe.
Peppe LG
2

La razón principal por la que lo usaría onViewCreatedes porque separa cualquier lógica de inicialización de la lógica de creación / inflación de la jerarquía de vista que debería ir en onViewCreate. Todas las demás características de rendimiento tienen el mismo aspecto.

AmeyaB
fuente
2

Creo que la principal diferencia entre estos es cuando usa kotlin.in onCreateView () cada vez que desea acceder para ver en su archivo xml, debe usar findViewById pero en onViewCreated simplemente puede acceder a su vista simplemente llamando al id. .

Shahriar enayaty
fuente
¿Es esto realmente cierto? Obtengo nulo para la vista si solo uso la identificación en el código de cualquier manera. Necesito usar siempre findViewById.
Jim Leask
1
No, no lo es ... oncreate view crea una instancia de la vista, onviewcreated se llama después de oncreateview y antes de que se restauren los estados guardados ... es más un problema de tiempo en el ciclo de vida del fragmento
yo_
1

onCreateView se usa en fragmentos para crear diseño e inflar la vista. onViewCreated se usa para hacer referencia a la vista creada por el método anterior. Por último, es una buena práctica definir el oyente de acción en onActivityCreated.

Salu Khadka
fuente