Hace tiempo quería crear este mini tutorial, ya que en internet he visto demasiada información combinada, pero que puede marear a cualquier developer que solo busca información concisa. Y para los no entendidos del tema, Retrofit es la librería más usada para hacer peticiones red(Consumir una Api) desde una aplicación Android. Estoy basándome en la información proporcionada del Android Developer Aris Guimerá en su curso de Open Webinars, dejo el link para que compren el curso que me parece excelente. https://openwebinars.net/academia/portada/api-retrofit2-kotlin/
Ahora sí vamos al lio!
1.- Instalamos las librerías necesarias(Retrofit2, Gson,OkHttp3, loggin-interceptor, corrutinas)
- Retrofit2: Librería para hacer las peticiones
- Gson: Para transformar la información que nos llega de la api a una forma muy sencilla de trabajar. para "Parsear"
- OkHttp3 : Librería que nos provee de funciones que nos ayudan al momento de trabajar con Retrofit
- logging-interceptor : Para llevar un tracking de la respuesta que nos llega, mediante logcat
- Corrutinas: Trabajar en segundo hilo.
4.- Nos olvidamos de activar el viewBinding true en el gradle, ya que usaremos esto para relacionar las vistas y no tener problemas nulidad al llamar ids. Pues lo ponemos!
6.- Creamos un fichero llamado API, lo hacemos con Singleton para crear una única instancia del objeto Retrofit
7.- Crear una Interface que defina el contrato entre nuestra API y nosotros, para ver bien el json que nos trae podemos usar https://jsoneditoronline.org/.
Ya tenemos el modelo de datos listo.
9.- Conectamos el Api Service con el Api
10.- Implementando la corrutinas para no hacerlo en el hilo principal.
11.- Ahora que ya sabemos que hace la petición correcta, hacemos la petición real.
Haremos la llamada Post . Se tiene que modelar el objeto correctamente si queremos que funcione.
Añadimos el Header, el post y FormUrlEncoded
@Headers("Authorization: Bearer 657271e907c55609174816fb78716aa8")
@FormUrlEncoded
@POST ("0.2/detect")
suspend fun getTxtLanguage(@Field("q")text:String )
Entonces, primero creamos una data class y la llamamos DetectionResponse.
Este data class va a contener un objeto llamado data , entonces creamos otro data class y la llamamos Data, y esta clase data va contener un listado de detection y
Ya tenemos creada la petición post!
private fun getTextLanguage(text: String) {
CoroutineScope(Dispatchers.IO).launch {
var result = retrofitService.getTxtLanguage(text)
if (result.isSuccessful) {
checkResult(result.body())
} else {
showError()
}
}
}
Lo analizamos asi : Si detectionResponse es distinto de null y si este listado no es nulo ni vacío, pues haz algo
private fun checkResult(detectionResponse: DetectionResponse?) {
if (detectionResponse != null && !detectionResponse.data.detections.isNullOrEmpty()) {
val correctLanguages= detectionResponse.data.detections.filter { it.isReliable }
if (correctLanguages.isNotEmpty()) {
runOnUiThread {
Toast.makeText(
this,
"El idioma es ${correctLanguages.first().language}", Toast.LENGTH_SHORT
).show()
}
}
}
}
Probamos
private lateinit var progressBar: ProgressBar
private fun initView() {
btnDetectLanguage = binding.btnDetectLanguage
etDescription = binding.etDescription
progressBar = binding.progressBar
}
private fun initListener() {
btnDetectLanguage.setOnClickListener {
val text = etDescription.text.toString()
if (text.isNotEmpty()) {
showLoading()
getTextLanguage(text)
}
}
}
Ahora le decimos que la función showLoading sea Visible cuando den click en el botón
private fun showLoading() {
progressBar.visibility= View.VISIBLE
}
Y ahora creamos la funcion hideLoading cuando funcione o no funcione se esconda el progressBar
private fun showLoading() {
progressBar.visibility= View.VISIBLE
}
private fun hideLoading() {
progressBar.visibility= View.GONE
}
Añadimos el cleanText, para que cuando finalice se limpie el campo.
private fun cleanText() {
etDescription.setText("")
}
14.- Usaremos logging interceptor , creamos la variable logging en la clase API
object API {
private const val BASE_URL = "https://ws.detectlanguage.com/"
val retrofitService: ApiService by lazy {
getRetrofit().create(ApiService::class.java)
}
private fun getRetrofit(): Retrofit {
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
val httpClient=OkHttpClient.Builder()
httpClient.addInterceptor(logging)
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build()
}
}
private fun showLoading() {
progressBar.visibility = View.VISIBLE
}
private fun hideLoading() {
runOnUiThread {
progressBar.visibility = View.GONE
}
}
private fun getTextLanguage(text: String) {
CoroutineScope(Dispatchers.IO).launch {
var result = retrofitService.getTxtLanguage(text)
if (result.isSuccessful) {
checkResult(result.body())
} else {
showError()
}
cleanText()
hideLoading()
}
}