Taller de Desarrollo Móvil en Android

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

Práctica 6: Comunicación con Servicios Web

Objetivo: Implementar el cliente HTTP Retrofit para realizar peticiones asíncronas a una API REST. Aprenderemos a mapear un archivo JSON a objetos de datos en Kotlin y mostrarlos en nuestra interfaz.

Paso 1: Permisos y Dependencias

Android requiere permisos explícitos para usar el hardware de red y librerías externas para procesar JSON.

📍 Archivo: app > manifests > AndroidManifest.xml

Agrega esta línea arriba de la etiqueta <application>:

<uses-permission android:name="android.permission.INTERNET" />
📍 Archivo: Gradle Scripts > build.gradle.kts (Module :app)

Agrega estas librerías en el bloque dependencies { ... }:

dependencies {
    // Retrofit para peticiones HTTP
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    // Convertidor Gson para transformar JSON a Objetos Kotlin
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
}

⚠️ Haz clic en "Sync Now".

Paso 2: Definir el Modelo de Datos (Data Class)

Debemos crear una clase que represente la estructura del JSON que vamos a recibir.

📍 Nuevo Archivo: UserResponse.kt (En tu paquete principal)
package mx.lasalle.ciclovida

// Definimos los campos exactos que vienen en el JSON de la API
data class UserResponse(
    val id: Int,
    val name: String,
    val username: String,
    val email: String
)

Paso 3: Crear la Interfaz del Servicio

Aquí definimos los "Endpoints" o rutas de la API a las que queremos acceder.

📍 Nuevo Archivo: ApiService.kt
package mx.lasalle.ciclovida

import retrofit2.Response
import retrofit2.http.GET

interface ApiService {
    // Definimos una petición GET a la ruta /users
    @GET("users")
    suspend fun getAllUsers(): Response<List<UserResponse>>
}

Paso 4: Implementación en HomeActivity

Configuraremos Retrofit y realizaremos la llamada en un hilo secundario (Coroutine).

📍 Archivo: HomeActivity.kt
// ... (Tus imports actuales)
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class HomeActivity : AppCompatActivity() {
    private lateinit var binding: ActivityHomeBinding

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

        // Ejecutamos la petición al iniciar la pantalla
        getUsersFromApi()
    }

    private fun getUsersFromApi() {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://jsonplaceholder.typicode.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val service = retrofit.create(ApiService::class.java)

        // Usamos Corrutinas para no bloquear la interfaz de usuario
        CoroutineScope(Dispatchers.IO).launch {
            val response = service.getAllUsers()
            
            runOnUiThread {
                if (response.isSuccessful) {
                    val listaUsuarios = response.body() ?: emptyList()
                    // Mapeamos los nombres para nuestro Adapter actual
                    val nombres = listaUsuarios.map { it.name }
                    binding.rvUsuarios.adapter = UserAdapter(nombres)
                } else {
                    Toast.makeText(this@HomeActivity, "Error de red", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

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

1. Arquitectura Cliente-Servidor:

¿Por qué es obligatorio el uso de Dispatchers.IO al realizar una petición con Retrofit? ¿Qué sucedería si intentamos hacer la petición en el hilo principal (Main Thread)?

2. Serialización de Datos:

Explica la función del GsonConverterFactory. ¿Qué proceso realiza exactamente entre el texto JSON recibido de internet y nuestra data class de Kotlin?

3. Seguridad en Red:

Si la URL de la API fuera http en lugar de https, la aplicación fallaría por políticas de seguridad de Android. ¿Cómo se llama el permiso o configuración necesaria para permitir tráfico de "texto claro" (Cleartext Traffic)?

💡 Nota para el reporte: Incluye una captura de pantalla del Logcat donde se vea la respuesta exitosa de la API y otra de tu RecyclerView mostrando los nombres obtenidos de internet (ej. Leanne Graham, Ervin Howell).