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.
- ¿Cómo puedo obtener un Android TableLayout para llenar la pantalla?
- Cómo acceder a una cadena utilizando un nombre de cadena dinámica en android (similar a eval en javascript)?
- Android: abre o reinicia la aplicación después de hacer clic en la notificación push mediante las actividades de bandera
- Android: ¿cómo obtener el sexo y la edad del usuario?
- Android OnResume no se llama cuando se usa TabHost y LocalActivityManager
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?
- Proyecto LibGDX escrito en Scala, en Android, con IntelliJ
- Android enviar SMS automáticamente al hacer clic en el botón
- Restlet en Android - Problemas con la serialización
- Android: ListView no muestra ningún resultado
- OnCreateView Fragmento no llamado
- Java.net.URLEncoder.encode codifica espacio como + pero necesito% 20
- JNI CALL cambia el parámetro jclass o cómo obtener un jobject desde un parámetro jclass
- ¿Cómo configurar el formato de 24 horas para la fecha en java?
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 suFragment
(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 unaActivity
tal cual a unFragment
incrustado en el diseño; Por ejemplo, a menudo uso esto cuando tengo unaActivity
que muestra unFragment
"pantalla completa" y necesita algún ID (oContentProvider
URI) para saber qué mostrar / hacer. A veces incluso añadir más cosas a unBundle
(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 unaActivity
, 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 enonCreate()
,onViewCreate()
, etc no es tan malo. -
Para el tipo de seguridad,
Bundle
tiene todos los diferentes métodosgetXXXX()
, 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.
- Una sola intención de permitir que el usuario tome una foto O escoge una imagen de la galería en Android
- El teclado virtual de Android nunca aparece en el emulador