![]() |
|
| 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 |
«
Tema Anterior
|
Siguiente tema
»
|
|
Herramientas |
|
#1
|
||||
|
||||
|
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) |
|
|
|
#2
|
||||
|
||||
|
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 |
|
#3
|
||||
|
||||
|
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 |
|
#4
|
||||
|
||||
|
¿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
}
}
}
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 |
| Gracias de parte de: | ||
|
#5
|
||||
|
||||
|
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 |
|
#6
|
||||
|
||||
|
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. |
|
#7
|
|
|
Cita:
|
| Respuesta |
Estás aquí
|
||||||
|
||||||
«
Tema Anterior
|
Siguiente tema
»
|
|
Hora actual: 03:22:42 (GMT +1)
HTCMania: líderes desde el 2007






