Variables de miembro vs setArguments en Fragments

He notado que en la referencia de Android para Fragmentos (notablemente DialogFragment ) que hacen un par de cosas diferentes de lo que yo esperaría:

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

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

¿Alguna idea?

También he tropezado con esto y he encontrado algunas ventajas al usar los argumentos Bundle sobre los campos de la instancia:

  • Si está en un Bundle el sistema Android lo sabe y puede crear y destruir su Fragment (utilizando el método obligatorio de parametrización / predeterminado y los métodos de ciclo de vida habituales) y simplemente pasar el paquete de argumentos de nuevo. De esta manera, no se pierden argumentos en una matanza de baja memoria o en los eventuales cambios de orientación (esto a menudo me golpea en el primer despliegue a un dispositivo real después del desarrollo en el emulador menos giratorio).

  • Usted puede simplemente pasar el Bundle adicional de una Activity tal cual 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 necesita algún ID (o ContentProvider URI) para saber qué mostrar / hacer. A veces incluso añadir 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 mencionó:

  • Creo que la sobrecarga es mínima porque es muy probable que no se consulte el Bundle en un bucle ajustado, por lo que obtener sus datos de argumento una vez en onCreate() , onViewCreate() , etc no es tan malo.

  • Para el tipo de seguridad, 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 MyFragment newInstance(String singleIdOfWhatToDisplay) un nuevo MyFragment newInstance(String singleIdOfWhatToDisplay) que crea tanto el Bundle como el Fragment de una sola vez y devuelve una instancia de Fragment lista para Fragment .

Me pareció que esto era un tema altamente confuso (uno de los muchos que la basura el paisaje de Android).

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

Mi confusión llegó en olas. Primero, los métodos que naturalmente anulan en su Fragment (por ejemplo, onCreateView , onCreateView ) reciben un parámetro Bundle que representa el savedInstanceState de su Fragment . Aparentemente, este estado de instancia no tiene nada que ver con los valores que almacena a través de setArguments() y recupera a través de getArguments() . Ambos utilizan un Bundle , es probable que ambos Bundles tengan acceso dentro del mismo método anulado, ni tienen nada que ver con el otro.

En segundo lugar, no está claro cómo Android utiliza setArguments() . Android llama a tu constructor sin parámetros para reconstruir tu Fragment al rotar, pero al parecer también llamará al método setArguments() que se llamó por última vez cuando se setArguments() el Fragment .

Huh ????

Increíble, pero cierto. Todo esto crear setArguments() con setArguments() locura existe para compensar la necesidad de un parámetro-menos Fragment constructor.

En resumen, estoy usando el método estático newInstance 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 } } 

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

El constructor de Fragmentos no puede tener ningún parámetro. Cuando su actividad está detenida, su 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 supiera cuáles son los tipos y valores para los argumentos de su constructor Fragmentos?

No creo que el paquete sea lanzado. El paquete se mantiene alrededor precisamente de modo que se puede pasar de nuevo a su fragmento después de que se ha recreado con el constructor predeterminado.

Philipp Reichart eludido a esto en su puesto (en realidad más que eludido.)

Sólo quiero añadir un inconveniente más a los argumentos es que usted tiene que crear dinámicamente fragmentos. Como argumentos no funciona muy bien si se crea desde el xml. Y de verdad odio eso.

  • Haciendo la vista de lista de android desplazable
  • Implementación cliente / servidor de socket TCP de Android
  • Android El registro y reproducción de audio está dañado
  • Tabulaciones desplazables de Android + estado de desplazamiento al pasar
  • No se pudo agregar entrada ': app: sourceSets' para almacenar en caché taskArtifacts.bin
  • Flujo de trabajo de desarrollo de aplicaciones Android más eficiente?
  • ¿Puede alguien explicarme por qué esta filtración?
  • Lectura de un archivo de texto en Android Studio Java
  • Android AutoCompleteTextView con chips
  • onclicklistener en el elemento específico de la recyclerview en android
  • Renderización de Android OpenGLES con C ++ y Java
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.