He visto dos prácticas generales para instanciar un nuevo Fragmento en una aplicación:
Fragment newFragment = new MyFragment();
y
Fragment newFragment = MyFragment.newInstance();
La segunda opción hace uso de un método estático newInstance()
y generalmente contiene el siguiente método.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Al principio, pensé que el principal beneficio era el hecho de que podía sobrecargar el método newInstance () para dar flexibilidad al crear nuevas instancias de un Fragmento, pero también podía hacerlo creando un constructor sobrecargado para el Fragmento.
¿Me he perdido algo?
¿Cuáles son los beneficios de un enfoque sobre el otro? ¿O es solo una buena práctica?
android
android-fragments
Graham Smith
fuente
fuente
Respuestas:
Si Android decide recrear su Fragmento más tarde, llamará al constructor sin argumentos de su fragmento. Por lo tanto, sobrecargar el constructor no es una solución.
Dicho esto, la forma de pasar cosas a tu Fragment para que estén disponibles después de que Android haya recreado un Fragment es pasar un paquete al
setArguments
método.Entonces, por ejemplo, si quisiéramos pasar un número entero al fragmento, usaríamos algo como:
Y más adelante en el Fragmento
onCreate()
puedes acceder a ese número entero usando:Este paquete estará disponible incluso si el fragmento es recreado de alguna manera por Android.
También tenga en cuenta:
setArguments
solo se puede llamar antes de que el Fragmento se adjunte a la Actividad.Este enfoque también está documentado en la referencia del desarrollador de Android: https://developer.android.com/reference/android/app/Fragment.html
fuente
El único beneficio al usar lo
newInstance()
que veo son los siguientes:Tendrá un solo lugar donde todos los argumentos utilizados por el fragmento podrían agruparse y no tiene que escribir el código a continuación cada vez que cree una instancia de un fragmento.
Es una buena manera de decirle a otras clases qué argumentos espera que funcionen fielmente (aunque debería ser capaz de manejar casos si no hay argumentos agrupados en la instancia del fragmento).
Entonces, mi opinión es que usar una estática
newInstance()
para instanciar un fragmento es una buena práctica.fuente
También hay otra forma:
fuente
instantiate()
Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Mientras que @yydl da una razón convincente sobre por qué el
newInstance
método es mejor:Todavía es bastante posible utilizar un constructor . Para ver por qué esto es así, primero debemos ver por qué Android usa la solución anterior.
Antes de que se pueda usar un fragmento, se necesita una instancia. Android llama
YourFragment()
(el constructor sin argumentos ) para construir una instancia del fragmento. Aquí se ignorará cualquier constructor sobrecargado que escriba, ya que Android no puede saber cuál usar.Durante la vida útil de una Actividad, el fragmento se crea como se describe arriba y Android lo destruye varias veces. Esto significa que si coloca datos en el propio objeto de fragmento, se perderá una vez que se destruya el fragmento.
Para solucionarlo, Android le pide que almacene datos utilizando un
Bundle
(llamadasetArguments()
), al que luego se puede acceder desdeYourFragment
. Los argumentosbundle
están protegidos por Android y, por lo tanto, se garantiza que sean persistentes .Una forma de configurar este paquete es mediante el uso de un
newInstance
método estático :Sin embargo, un constructor:
puede hacer exactamente lo mismo que el
newInstance
método.Naturalmente, esto fallaría, y es una de las razones por las que Android quiere que uses el
newInstance
método:Como explicación adicional, aquí está la Clase de Fragmento de Android:
Tenga en cuenta que Android solicita que los argumentos se establezcan solo en la construcción y garantiza que se retendrán.
EDITAR : Como se señaló en los comentarios de @JHH, si proporciona un constructor personalizado que requiere algunos argumentos, Java no proporcionará a su fragmento un constructor predeterminado sin argumentos . Por lo tanto, esto requeriría que defina un constructor sin argumentos , que es un código que podría evitar con el
newInstance
método de fábrica.EDITAR : Android ya no permite usar un constructor sobrecargado para fragmentos. Debes usar el
newInstance
método.fuente
No estoy de acuerdo con la respuesta de yydi diciendo:
Creo que es una solución y una buena, esta es exactamente la razón por la que fue desarrollada por el lenguaje central de Java.
Es cierto que el sistema Android puede destruir y recrear tu
Fragment
. Entonces puedes hacer esto:Le permitirá avanzar
someInt
desdegetArguments()
este último, incluso si el sistema loFragment
ha recreado. Esta es una solución más elegante que elstatic
constructor.En mi opinión, los
static
constructores son inútiles y no deberían usarse. También lo limitarán si en el futuro desea ampliar estoFragment
y agregar más funcionalidades al constructor. Con elstatic
constructor no puedes hacer esto.Actualizar:
Android agregó una inspección que marca todos los constructores no predeterminados con un error.
Recomiendo deshabilitarlo, por las razones mencionadas anteriormente.
fuente
Algún código de kotlin :
Y puedes obtener argumentos con esto:
fuente
La mejor práctica para instanciar fragmentos con argumentos en Android es tener un método de fábrica estático en su fragmento.
Debe evitar configurar sus campos con la instancia de un fragmento. Porque cada vez que el sistema Android recrea tu fragmento, si siente que el sistema necesita más memoria, entonces recreará tu fragmento usando un constructor sin argumentos.
Puede encontrar más información sobre las mejores prácticas para crear instancias de fragmentos con argumentos aquí.
fuente
Desde las preguntas sobre las mejores prácticas, agregaría, que a menudo es una buena idea utilizar un enfoque híbrido para crear fragmentos al trabajar con algunos servicios web REST
No podemos pasar objetos complejos, por ejemplo, algún modelo de usuario, para el caso de mostrar fragmentos de usuario
Pero lo que podemos hacer es registrar a
onCreate
ese usuario! = Nulo y si no, luego traerlo de la capa de datos, de lo contrario, usar el existente.De esta manera, obtenemos tanto la capacidad de recrear por ID de usuario en caso de recreación de fragmentos por parte de Android como la facilidad para las acciones del usuario, así como la capacidad de crear fragmentos al mantener el objeto en sí o solo su ID
Algo le gusta esto:
fuente
User user = /*...*/
coloque al usuario en el paquete:Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user);
y obtenga al usuario de argumentos:User user = getArguments().getParcelable("some_user");
el objeto debe implementar la interfaz Parcelable. enlaceusa este código 100% soluciona tu problema
ingrese este código en el primer fragmento
esta muestra envía datos booleanos
y en SecendFragment
código feliz
fuente
La mejor manera de crear una instancia del fragmento es usar el método predeterminado Fragment.instantiate o crear un método de fábrica para crear una instancia del fragmento
Precaución: siempre cree un constructor vacío en otro fragmento mientras restaura la memoria del fragmento generará una excepción en tiempo de ejecución.
fuente
Últimamente estoy aquí. Pero algunas cosas que acabo de saber que podrían ayudarte un poco.
Si está utilizando Java, no hay mucho que cambiar. Pero para los desarrolladores de kotlin, aquí hay un fragmento de código siguiente que creo que puede convertirlo en un sótano para ejecutar:
Feliz codificación
fuente
setArguments()
es inútil Solo trae un desastre.fuente
onViewCreated
alcance. Es conveniencia, supongo, muchas formas de hacer lo mismo. También es una manera fácil de verificar las actualizaciones realizadas por el usuario (compare los paquetes degetArguments
y el paquete deonSaveInstanceState
)getArguments
cosas. ¿Qué pasa con elonViewCreated
alcance ... Podemos restaurar el paquete de estado allí. Pero prefiero haceronCreateView
que la inicialización sea ligera y rápida, y hacer todas las inicializaciones pesadas dentro de una,onActivityCreated
porque aFragment.getActivity()
veces me gusta regresarnull
y debido a losonAttach()
cambios en la nueva versión de API 23.set
yget
Arguments
entrarsaveInstanceState
. Básicamente estás haciendo lo mismo que se hace "bajo el capó"saveInstanceState
es "debajo del capó". Y el uso deArguments
es una duplicación de la funcionalidad que hace que verifique dos veces: primeroArguments
valores y luegosaveInstanceState
valores. Porque tienes que usar desaveInstanceState
cualquier manera. ¿Qué pasa conArguments
... no son necesarios.Creo que tengo una solución mucho más simple para esto.
fuente