Fragmento – ¿Debo reutilizar la vista en onCreateView y cómo debo hacerlo?

En realidad, siempre he reutilizado mi punto de vista en mis fragmentos como el siguiente:

private View mView = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mView == null) mView = inflater.inflate(R.layout.view); return mView; } 

Eso funcionó, con viewpager y así sucesivamente. Ahora empecé a usar mis fragmentos en actividades simples y si, y sólo si, agrego el fragmento a la backstack, esto fallará debido a java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Así que mis preguntas son:

  • ¿Está bien, si compruebo el padre de las vistas, quítelo y lo agrego al nuevo padre?
  • ¿O debo recrear siempre la vista y nunca volverla a usarla? ¿Si es así por qué?
  • ¿Hay otros puntos, donde la reutilización de la vista fallará?

Tal vez esto puede ayudar a entender el comportamiento. Si echa un vistazo a FragmentManagerImpl.java encontrará lo siguiente:

Primero creamos una vista llamando a onCreateView() ( línea 845 ) y luego envolviendo la vista creada con otra vista, que se convierte en un padre de nuestra vista ( líneas 848-849 ). Esto significa que nuestra visión no se convierte en un niño de contenedor real, pero es un niño de una vista de envoltura ahora. El problema con la reutilización sucede cuando la vista se quita del contenedor ( línea 998 ). FragmentManager elimina la vista del contenedor del contenedor, pero nuestra vista real permanece agregada a la vista del contenedor principal. Esto es lo que causa el problema que experimenta.

Por lo tanto, si quita la vista de su padre, puede funcionar. Aún sabiendo esto, no recomendaría reutilizar las vistas en el fragmento también porque las vistas pueden vivir un poco más que los fragmentos, porque pueden ser usadas en "desaparecer" las animaciones incluso después de que el fragmento ha sido destruido. Si intenta quitar una vista de este tipo de su padre en ese momento, entonces la animación se puede romper.

Otro argumento para no almacenar la vista en caché es que Android no admite el reciclaje de vistas en fragmentos por diseño. ¿Recuerda ListAdapter permitiendo reutilizar las vistas? Android cuida el almacenamiento en caché y la correcta reutilización de esas vistas. Esto no es el caso con el fragmento sin embargo.

Actualmente estoy reutilizando la vista con algo como esto:

 if(view == null){ view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false); } else { ((ViewGroup) view.getParent()).removeView(view); } return view; 

No sé si esta manera es correcta, pero parece que funciona para mí ..

NOTA: Estoy usando este approach porque tengo un listview en un fragmento, y cuando el usuario golpea ligeramente en un artículo que carga un nuevo fragmento (el encargado del fragmento substituye el fragmento actual de la lista usando). Entonces, cuando el usuario pulsa backbutton, ya que estoy reutilizando la misma vista antigua del fragmento (que no se destruye cuando se elimina con FM), el usuario continúa viendo la lista en la posición que tenía antes de abrir la vista de fragmento de detalle.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.