Jve386 / NativeNinjas-Apps

JAVA & Kotlin Android app: Random gameplay vs PC. DAO, MVVM, SQLite integration, Firebase API Rest, Coroutines, Google Maps
1 stars 2 forks source link

- Añadir frases randoms al iniciar la app para hacer uso de manejo de JSON y Retrofit. #41

Closed Jve386 closed 4 months ago

Jve386 commented 4 months ago

Objeto RetrofitHelper se usa para configurar y proporcionar una instancia de Retrofit preconfigurada. Retrofit es una librería de Java y Android que permite realizar peticiones HTTP de manera sencilla, especialmente útil para consumir APIs REST. En este caso, con un convertidor Gson y una URL base definida.

object RetrofitHelper {
    fun getRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://piedrapapeltijeras-8e6be-default-rtdb.europe-west1.firebasedatabase.app/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}
Jve386 commented 4 months ago

La clase QuoteModel es un modelo de datos que facilita la conversión entre JSON y objetos Kotlin, permitiendo manipular fácilmente los datos que se obtienen de una API o de cualquier fuente que proporcione datos en formato JSON. La anotación @SerializedName asegura que los nombres de los campos en el JSON se correspondan correctamente con los nombres de las propiedades en la clase.

data class QuoteModel(
    @SerializedName("quote") val quote: String,
    @SerializedName("author") val author: String
)
Jve386 commented 4 months ago

QuoteProvider actúa como un contenedor global para una lista de QuoteModel. El uso del companion object permite acceder a la lista de citas desde cualquier parte de la aplicación sin necesidad de instanciar la clase QuoteProvider. Esto es útil para gestionar datos compartidos o configuraciones que deben ser accesibles globalmente en la aplicación.

class QuoteProvider {
    companion object {

        var quotes:List<QuoteModel> = emptyList()

    }
}
Jve386 commented 4 months ago

define un cliente de API para realizar una petición GET al endpoint /.json para obtener una lista de citas (QuoteModel). Utiliza anotaciones de Retrofit para especificar el tipo de petición y el endpoint, y retorna un objeto Response que contiene la respuesta de la API. Al ser una función suspendida, puede ser llamada de manera asíncrona usando coroutines en Kotlin, lo que permite manejar operaciones de red sin bloquear el hilo principal de la aplicación.

interface QuoteApiClient {
    @GET("/.json")
    suspend fun getAllQuotes(): Response<List<QuoteModel>>
}
Jve386 commented 4 months ago

La clase QuoteService encapsula la lógica necesaria para interactuar con el cliente de API (QuoteApiClient) y obtener una lista de citas. Utiliza Retrofit para realizar la solicitud de red y Kotlin Coroutines para manejar la operación de manera asincrónica y eficiente, cambiando al contexto de I/O para evitar bloquear el hilo principal.

class QuoteService {

    private val retrofit = RetrofitHelper.getRetrofit()

    suspend fun getQuotes(): List<QuoteModel> {
        return withContext(Dispatchers.IO) {
            val response = retrofit.create(QuoteApiClient::class.java).getAllQuotes()
            response.body() ?: emptyList()
        }
    }

}
Jve386 commented 4 months ago

La clase QuoteRepository sirve como una capa de abstracción entre el servicio de red (QuoteService) y el proveedor de datos global (QuoteProvider). Encapsula la lógica para obtener datos desde la API y actualiza el estado global de la aplicación con los datos obtenidos. Este enfoque hace que el código sea más modular y facilita la gestión de datos y su disponibilidad en diferentes partes de la aplicación.

class QuoteRepository {

    private val api = QuoteService()

    suspend fun getAllQuotes(): List<QuoteModel> {
        val response = api.getQuotes()
        QuoteProvider.quotes = response
        return response
    }
}
Jve386 commented 4 months ago

La clase GetQuotesUseCase encapsula la lógica de negocio para obtener todas las citas de la aplicación. Actúa como un punto de entrada para interactuar con la capa de datos (QuoteRepository) sin exponer directamente los detalles de implementación. Este enfoque sigue los principios de la arquitectura limpia (Clean Architecture) al separar las preocupaciones y facilitar la prueba y la mantenibilidad del código.

class GetQuotesUseCase {
    private val repository = QuoteRepository()
    suspend operator fun invoke() = repository.getAllQuotes()
}
Jve386 commented 4 months ago

La clase GetRandomQuoteUseCase encapsula la lógica para obtener una cita aleatoria de la lista de citas disponibles. Actúa como un punto de entrada para interactuar con el proveedor de citas (QuoteProvider) sin exponer directamente los detalles de implementación. Este enfoque sigue los principios de la arquitectura limpia (Clean Architecture) al separar las preocupaciones y facilitar la prueba y la mantenibilidad del código.

class GetRandomQuoteUseCase {

    operator fun invoke():QuoteModel?{
        val quotes = QuoteProvider.quotes
        if(!quotes.isNullOrEmpty()){
            val randomNumber = (quotes.indices).random()
            return quotes[randomNumber]
        }
        return null
    }
}
Jve386 commented 4 months ago

La clase QuoteViewModel actúa como un intermediario entre la capa de presentación y la capa de datos de la aplicación, gestionando la lógica de presentación y la interacción con los casos de uso relacionados con las citas. Utiliza LiveData para notificar cambios en los datos de manera reactiva, y coroutines para ejecutar operaciones de manera asíncrona. Este enfoque sigue los principios de la arquitectura de Android Jetpack, facilitando la separación de preocupaciones y la creación de aplicaciones robustas y mantenibles.

class QuoteViewModel : ViewModel() {

    val quoteModel = MutableLiveData<QuoteModel>()
    val isLoading = MutableLiveData<Boolean>()

    private val getQuotesUseCase = GetQuotesUseCase()
    private val getRandomQuoteUseCase = GetRandomQuoteUseCase()

    fun onCreate() {
        viewModelScope.launch {
            isLoading.postValue(true)
            val result = getQuotesUseCase()

            if (!result.isNullOrEmpty()) {
                quoteModel.postValue(result[0])
                isLoading.postValue(false)
            }
        }
    }

    fun randomQuote() {
        isLoading.postValue(true)
        val quote = getRandomQuoteUseCase()
        quote?.let {
            quoteModel.postValue(it)
        }
        isLoading.postValue(false)
    }
}
Jve386 commented 4 months ago

Implementación en el mainActivity y Layout para plasmar la función en el menú principal, utilizando el patrón de arquitectura MVVM (Modelo-Vista-ViewModel) con LiveData para observar cambios en los datos y ejecutar acciones en respuesta a esos cambios.

        tvQuote = findViewById(R.id.tvQuote);

        quoteViewModel = new ViewModelProvider(this).get(QuoteViewModel.class);
        quoteViewModel.onCreate();

        quoteViewModel.getQuoteModel().observe(this, new Observer<QuoteModel>() {
            @Override
            public void onChanged(QuoteModel quoteModel) {
                tvQuote.setText(quoteModel.getQuote());
                Log.d("MainActivity", "Quote updated: " + quoteModel.getQuote());
            }
        });

        tvQuote.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("MainActivity", "TextView clicked");
                quoteViewModel.randomQuote();
            }
        });