tutorial style studio guide fragments example ejemplo dinamicos coding java android coding-style android-fragments

java - style - fragments android tutorial



Variables de miembros frente a setArguments en Fragments (4)

Encontré que se trata de un tema ALTAMENTE confuso (uno de los tantos que ensucian el panorama de Android).

setArguments() es una solución para la muy poco útil necesidad de Android de tener un constructor sin parámetros disponible para los Fragmentos.

Mi confusión vino en oleadas. En primer lugar, los métodos que anula de forma natural en su Fragment (p. onCreate , onCreateView , onCreateView ) reciben un parámetro Bundle que representa el savedInstanceState de su Fragment . Este estado de instancia aparentemente no tiene NADA que ver con los valores que almacena a través de setArguments() y recupera a través de getArguments() . Ambos usan un Bundle , es probable que se acceda a ambos Bundles dentro del mismo método reemplazado, ninguno tiene nada que ver el uno con el otro.

En segundo lugar, no está claro cómo Android usa setArguments() . Android llama a tu constructor sin parámetros para reconstruir tu Fragment on rotate, pero aparentemente TAMBIÉN setArguments() método que setArguments() llamado a setArguments() cuando se construyó el Fragment .

Huh ???

Increíble, pero cierto. Todo esto crea Bundles with setArguments() locura existe para compensar la necesidad de un constructor de Fragment parámetros.

En resumen, estoy usando el método newInstance estático para crear mi Fragment .

public MyFragment() { //satisfy Android } public static MyFragment newInstance(long record_id) { Log.d("MyFragment", "Putting " + record_id + " into newInstance"); MyFragment f = new MyFragment(); Bundle args = new Bundle(); args.putLong("record_id", record_id); f.setArguments(args); return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * Perform an immediate check of arguments, * which ARE NOT the same as the bundle used * for saved instance state. */ Bundle args = getArguments(); if(args != null) { record_id = args.getLong("record_id"); Log.d("MyFragment", "found record_id of " + String.valueOf(record_id)); } if(savedInstanceState != null) { //now do something with savedInstanceState } }

Me di cuenta de que en la referencia de Android para Fragments (en particular, DialogFragment ) hacen un par de cosas diferentes de lo que esperaba:

1). Utilice public static foo newInstance() método public static foo newInstance() lugar de un constructor.
2). Pase los valores a onCreateDialog utilizando setArguments en lugar de variables miembro.

He leído que newInstance parece ser preferible cuando se usa la reflexión. Sin embargo, realmente no entiendo por qué están pasando parámetros a través de un paquete. Sin embargo, hubiera usado variables de miembro sería más seguro (no usar una cadena para recuperar de un mapa) y tendría menos de una sobrecarga.

¿Alguna idea?


Solo quiero agregar una desventaja más a los argumentos es que tienes que crear fragmentos dinámicamente. Como argumentos, no funciona muy bien si crea desde el xml. Y realmente odio eso.


Soy bastante nuevo en la programación de Android, pero esta es mi comprensión actual del problema:

El constructor para Fragmentos no puede tener ningún parámetro. Cuando tu actividad está en pausa, tu Fragmento puede ser liberado. Antes de reanudar su actividad, el sistema crea una nueva versión de su Fragmento llamando al constructor. Si se utiliza un constructor no predeterminado, ¿cómo se supone que Android sabrá cuáles son los tipos y valores para los argumentos de tu constructor de Fragments?

No creo que ese paquete sea lanzado. El paquete se mantiene alrededor precisamente para que pueda volver a pasar a su Fragmento después de que se haya recreado con el constructor predeterminado.

Philipp Reichart eludió esto en su publicación (en realidad más que eludido).


También me encontré con esto y encontré algunas ventajas al usar los argumentos Bundle sobre los campos de instancia:

  • Si está en un Bundle el sistema Android lo sabe y puede crear y destruir tu Fragment (utilizando el constructor obligatorio y sin parámetros obligatorio y los métodos usuales del ciclo de vida), y simplemente vuelve a pasar el paquete de argumentos. De esta manera, no se pierden argumentos en una juerga de poca memoria o la orientación eventual cambia (esto a menudo me golpea en la primera implementación en un dispositivo real después del desarrollo en el emulador menos giratorio).

  • Puede pasar el Bundle de extras de una Activity tal como está a un Fragment incrustado en el diseño; Por ejemplo, a menudo uso esto cuando tengo una Activity que muestra un Fragment "pantalla completa" y necesito alguna identificación (o URI del ContentProvider ) para saber qué mostrar / hacer. A veces incluso agrego más cosas a un Bundle (o una copia) antes de pasarlo, por ejemplo

    @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) { // not a re-creation final Bundle args = new Bundle(getIntent().getExtras()); args.putInt(CoverImageFragment.BACKGROUND_RESOURCE, android.R.color.black); final Fragment fragment = CoverImageFragment.newInstance(args); getSupportFragmentManager() .beginTransaction() .add(android.R.id.content, fragment) .commit(); } }

  • Mantiene la forma de desarrollar un Fragment cercano al de una Activity , es decir, Bundle como "parámetros de entrada, sin excepciones".

En cuanto a los inconvenientes que mencionaste:

  • Creo que la sobrecarga es mínima porque lo más probable es que no consulte el Bundle en un circuito cerrado, por lo que sacar los datos de su argumento una vez en onCreate() , en onViewCreate() , etc. no es tan malo.

  • Para la seguridad del tipo, Bundle tiene todos los diferentes métodos getXXXX() , e incluso sobrecargas para proporcionar un valor predeterminado si falta algo / opcional :)

En cuanto a los métodos newInstance() , pienso en ellos como una manera fácil de encapsular las llamadas new y setArguments() para mi Fragment ; A veces proporciono un MyFragment newInstance(String singleIdOfWhatToDisplay) adicional MyFragment newInstance(String singleIdOfWhatToDisplay) que crea tanto el Bundle como el Fragment de una vez y devuelve una instancia de Fragment lista para Fragment .