Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android


 
Herramientas
  #1  
Viejo 27/06/18, 22:41:20
Avatar de carlosmiller
carlosmiller carlosmiller no está en línea
Miembro del foro
Mensajes: 299
 
Fecha de registro: oct 2016
Mensajes: 299
Modelo de smartphone: Xiaomi Redmi Note 3 pro
Tu operador: Pepephone
Mencionado: 0 comentarios
Tagged: 0 hilos
interrogacion ¿Cómo enviar datos desde un activity a un fragment?

Hola a tod@s!
Hace poco tiempo que empecé con el desarrollo de aplicaciones y no tengo mucha idea todavía. A ver si alguien me puede echar una mano. Gracias

Antes de nada he de decir que la aplicación la estoy desarrollando en Kotlin.

El problema que tengo es el siguiente: Tengo un par de variables en un activity y quiero enviar esos datos a un fragment para poder usarlos en él y no se muy bien cómo hacerlo (tiene que ser en Kotlin)
Responder Con Cita


  #2  
Viejo 28/06/18, 09:57:15
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Muy buenas, empezaré diciendo que los fragments no me gustan nada porque su ciclo de vida es demasiado complejo.

Aunque hay varias formas de abordar el asunto, dado que estás empezando lo más sencillo es que en la clase donde defines el fragment crees un método con los parámetros que necesites y lo llames desde la actividad. En ese sentido es como un objeto cualquiera.

Ojo eso sí con guardar el estado del fragment en el onSaveInstanceState del fragment y recuperarlo en el onActivityCreated. Si le pasas los datos a través de tu método y a Android le parece bien destruir el fragment y volver a crearlo, no tendrás los datos cuando tu app vuelta a presentarse al usuario.

Si son datos de inicialización del fragment, en vez de pasarlos por constructor como harías en cualquier clase -hacer esto en fragments es pecado- , pasa un Bundle llamando al método setArguments justo después de crear el fragment. Esos datos que pases por el Bundle, Android te los va a guardar si tiene que recrear el fragment y tú no tienes que hacer nada, simplemente llamar al getArguments para leerlo en el fragment.

La tendencia actual de todas formas (que si estás empezando te vas a liar más todavía y puede ser matar moscas a cañonazos) es que no pases datos a nadie sino que los interesados se suscriban a los cambios de los datos y actúen en consecuencia cuando el valor cambia. Los datos deberían estar en un único sitio (el "modelo de datos"), y los demás simplemente usarlos. Para eso hay arquitecturas como MVVM usando frameworks como RxJava o las clases ViewModel y LiveData de Google que viene a ser el mismo concepto más orientado a Android.

Última edición por mocelet Día 28/06/18 a las 17:07:54
Responder Con Cita
  #3  
Viejo 03/07/18, 22:51:52
Avatar de carlosmiller
carlosmiller carlosmiller no está en línea
Miembro del foro
Mensajes: 299
 
Fecha de registro: oct 2016
Mensajes: 299
Modelo de smartphone: Xiaomi Redmi Note 3 pro
Tu operador: Pepephone
Mencionado: 0 comentarios
Tagged: 0 hilos
Muchas gracias por contestar, además tan rápido.
He estado intentándolo, pero sigo sin conseguirlo.

El código que estoy empleando es el siguiente:

En el activity:
val frag = NombresFragment()
val bundle =Bundle()
bundle.putString("Nombre", "Pedro")
frag.arguments = bundle

En el fragment:
val args= arguments
val index = args?.getString("Nombre")

Pero el problema que tengo es que me devuelve un valor nulo. No se si tengo algo mal, o no se hace de esta manera
Responder Con Cita
  #4  
Viejo 04/07/18, 07:18:16
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
¿El código del fragment dónde lo tienes puesto?

Debería ir en el onCreate o en otro método del ciclo de vida del fragment, si lo pones como variable de clase es normal que sea null porque el objeto se construye antes de haber llamado al setArguments.

Siendo Kotlin puedes hacer una inicialización lazy, que es una maravilla del lenguaje, de modo que cuando vayas a usar el atributo por primera vez sea cuando lo consulte y no antes. Si estuviéramos en Java tendrías que llamar al getString en el onCreate por ejemplo, pero nunca en el constructor o directamente al declarar la variable (que es lo mismo porque el valor se pone en el momento de la construcción).

Ya aprovecho y edito con un ejemplo de cómo se haría de la forma más elegante, aunque la clave para arreglar cómo lo tienes es la línea que pone val name by lazy o, simplemente, no guardarlo en una variable de clase y llamar al getString cuando lo necesites en el onCreateView o similar.

El resto es seguir recomendaciones habituales, por ejemplo:
- Las Strings escritas a mano mejor que sean constantes para no equivocarse al escribir lo mismo en dos sitios distintos. Imagina que en un sitio escribes "Nombre" y en otro "nombre", no funcionará y te volverás loco buscando.
- Cuando hay Bundle de inicialización de por medio, mejor que sea el propio fragment el que se construya a sí mismo con un método newInstance. Así quien quiera usarlo solo tiene que llamar a ese método y no se preocupa de crear bundles (imagina que tienes que llamarlo desde varias actividades, menudo rollete tener código duplicado)
- Los nombres de las variables deberían ser autodescriptivos. Por ejemplo, si llamas "index" a una variable, quien lo lea (otra persona o tú mismo en unos meses), espera que eso sea un valor numérico para acceder posiblemente a un array, y no una String como "Pedro" que es un nombre, no un índice de algo.

Código:
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val fragment = SampleFragment.newInstance("Pedro")
        supportFragmentManager.beginTransaction().replace(R.id.placeholder, fragment).commit()
    }
}
Código:
class SampleFragment: Fragment() {

    private val name by lazy { arguments.getString(ARGS_NAME) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Toast.makeText(context, name, Toast.LENGTH_SHORT).show()
    }

    companion object {
        private const val ARGS_NAME = "name";

        fun newInstance(name: String): Fragment{
            val args = Bundle()
            args.putString(ARGS_NAME, name)
            val fragment = SampleFragment()
            fragment.arguments = args
            return fragment
        }
    }

}
No le he puesto vista ni nada al fragment, pero si lo ejecutas verás que sale una tostada que pone Pedro. Si quitas lo del lazy te dará una NullPointerException porque en el momento de construir el objeto no hay ningún bundle todavía.

Evidentemente, no accedas al atributo fuera de los métodos del ciclo de vida del Fragment, o estaremos en las mismas

Última edición por mocelet Día 05/07/18 a las 10:22:42
Responder Con Cita
Gracias de parte de:
  #5  
Viejo 10/07/18, 12:10:55
Avatar de carlosmiller
carlosmiller carlosmiller no está en línea
Miembro del foro
Mensajes: 299
 
Fecha de registro: oct 2016
Mensajes: 299
Modelo de smartphone: Xiaomi Redmi Note 3 pro
Tu operador: Pepephone
Mencionado: 0 comentarios
Tagged: 0 hilos
Muchas gracias otra vez por responder y por los consejos.

Ya consigo la comunicación entre las 2 partes.

El código del fragment lo tenía (y lo sigo teniendo) en el onCreateView , el problema es que no conocía la inicialización lazy y supongo que al no inicializarla de esa manera era por lo que me devolvía un valor nulo.

Muchas gracias otra vez y tomo nota de los consejos
Responder Con Cita
  #6  
Viejo 30/07/18, 13:42:17
Avatar de carlosmiller
carlosmiller carlosmiller no está en línea
Miembro del foro
Mensajes: 299
 
Fecha de registro: oct 2016
Mensajes: 299
Modelo de smartphone: Xiaomi Redmi Note 3 pro
Tu operador: Pepephone
Mencionado: 0 comentarios
Tagged: 0 hilos
Hola de nuevo, siento volver a molestarte pero me surge otro problema con esto:

Al rotar la pantalla la aplicación deja de funcionar y no doy con el motivo.

En el logcast me sale:

Caused by: android.view.InflateException: Binary XML file line #57: Binary XML file line #57: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #57: Error inflating class fragment
Caused by: java.lang.IllegalStateException: Fragment aplicacion.android.fragments.MiFragment did not create a view.

Gracias de nuevo.
Responder Con Cita
  #7  
Viejo 18/11/18, 16:42:20
Avatar de wolfcat90
wolfcat90 wolfcat90 no está en línea
Desarrollador
Mensajes: 445
 
Fecha de registro: jun 2012
Mensajes: 445
Modelo de smartphone: Samsung Galaxy Trend Plus
Versión de ROM: Stock
Tu operador: Movistar
Mencionado: 4 comentarios
Tagged: 1 hilos
Cita:
Originalmente Escrito por carlosmiller Ver Mensaje
Hola de nuevo, siento volver a molestarte pero me surge otro problema con esto:

Al rotar la pantalla la aplicación deja de funcionar y no doy con el motivo.

En el logcast me sale:

Caused by: android.view.InflateException: Binary XML file line #57: Binary XML file line #57: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #57: Error inflating class fragment
Caused by: java.lang.IllegalStateException: Fragment aplicacion.android.fragments.MiFragment did not create a view.

Gracias de nuevo.
Eso se debe a que al girar la pantalla la aplicación se regenera y se vuelve a cargar el contenido. Mira el error de la linea 57 en el xml en el que tengas el Fragment. O directamente muestra tu xml completo.
Responder Con Cita
Respuesta

Estás aquí
Regresar   HTCMania > Todo sobre Android > Programación y Desarrollo para Android


Reglas de Mensajes
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Las caritas están On
Código [IMG] está On
Código HTML está Off

Saltar a Foro



Hora actual: 03:22:42 (GMT +1)

Cookies settings
Powered by vBulletin™
Copyright © vBulletin Solutions, Inc. All rights reserved.
 
HTCMania: líderes desde el 2007