Taller de Desarrollo Móvil en Android

Ingeniería de Software y Sistemas Computacionales | La Salle Nezahualcóyotl

Práctica 5: Modernización con ViewBinding

Objetivo: Migrar el proyecto hacia el uso de ViewBinding. Esta herramienta de Jetpack elimina la necesidad de usar findViewById, reduciendo errores de nulos y haciendo el código más mantenible.

Paso 1: Activación en Gradle

ViewBinding requiere que el compilador genere clases espejo de nuestros XML.

📍 Archivo: Gradle Scripts > build.gradle.kts (Module :app)

Dentro del bloque android { ... }, añade estas líneas al final:

android {
    ...
    viewBinding {
        enable = true
    }
}

⚠️ Haz clic en el botón "Sync Now" que aparecerá en la parte superior derecha de Android Studio.

Paso 2: Sustitución en MainActivity.kt

Observa cómo cambia la estructura. Ya no declaramos variables para cada botón, usamos un solo objeto binding.

📍 Archivo: MainActivity.kt

Sustituye todo tu archivo por el siguiente código:

package mx.lasalle.ciclovida

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.content.Intent
import android.widget.Toast
import mx.lasalle.ciclovida.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Inflado de vista con ViewBinding
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val prefs = getSharedPreferences("PREFS_SESION", MODE_PRIVATE)
        val usuarioGuardado = prefs.getString("USER_NAME", null)

        if (usuarioGuardado != null) {
            val intent = Intent(this, HomeActivity::class.java)
            intent.putExtra("USER_NAME", usuarioGuardado)
            startActivity(intent)
            finish()
        }

        // Acceso directo a los IDs del XML sin findViewById
        binding.btnEnviar.setOnClickListener {
            val nombreUsuario = binding.etNombre.text.toString()
            
            if (nombreUsuario.trim().isNotEmpty()) {
                val preferencias = getSharedPreferences("PREFS_SESION", MODE_PRIVATE)
                val editor = preferencias.edit()
                editor.putString("USER_NAME", nombreUsuario)
                editor.apply()

                val pasarPantalla = Intent(this, HomeActivity::class.java)
                pasarPantalla.putExtra("USER_NAME", nombreUsuario)
                startActivity(pasarPantalla)
            } else {
                Toast.makeText(this, "Por favor, ingresa un nombre", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

Paso 3: Sustitución en HomeActivity.kt

Eliminaremos los findViewById del RecyclerView y del botón de Logout.

📍 Archivo: HomeActivity.kt
package mx.lasalle.ciclovida

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import mx.lasalle.ciclovida.databinding.ActivityHomeBinding

class HomeActivity : AppCompatActivity() {

    private lateinit var binding: ActivityHomeBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        binding = ActivityHomeBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val usuarioPrincipal = intent.getStringExtra("USER_NAME") ?: "Invitado"
        val misDatos = listOf(
            usuarioPrincipal, "Sistemas Inteligentes", "Software de Calidad",
            "Redes de Computadoras", "Bases de Datos", "Seguridad Informática", "Sistemas Distribuidos"
        )

        // Acceso directo a rvUsuarios
        binding.rvUsuarios.adapter = UserAdapter(misDatos)

        // Acceso directo a btnCerrarSesion
        binding.btnCerrarSesion.setOnClickListener {
            val editor = getSharedPreferences("PREFS_SESION", MODE_PRIVATE).edit()
            editor.clear()
            editor.apply()

            Toast.makeText(this, "Sesión finalizada", Toast.LENGTH_SHORT).show()
            finish()
        }
    }
}

📝 Módulo de Evaluación: Práctica 5

1. Generación de Clases:

Si nuestro archivo XML se llama activity_main.xml, Android genera la clase ActivityMainBinding. ¿Cómo se llamaría la clase generada para un archivo llamado item_usuario.xml?

2. Seguridad de Nulos (Null Safety):

Explica por qué al usar ViewBinding es imposible que la aplicación truene por un "NullPointerException" al intentar acceder a un ID que no existe en el layout actual.

3. Ciclo de Vida:

¿Por qué es necesario declarar la variable binding como lateinit var fuera del método onCreate?

💡 Nota para el reporte: Compara el número de líneas de código entre la Práctica 4 y la Práctica 5. ¿En qué pantalla se redujo más el código?

5. Vinculación Automática:

Si creamos un nuevo archivo llamado configuracion_perfil.xml, ¿cuál sería el nombre exacto de la clase que Android Studio generará automáticamente para que podamos usar ViewBinding en su respectiva Activity?