Retrofit
qué es Retrofit
Crear un nuevo proyecto llamado DogsKotlin
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
build.gradle
buildFeatures {
viewBinding = true
}
Dependencias:
//Picasso
implementation("com.squareup.picasso:picasso:2.71828")
//RecyclerView
implementation("androidx.recyclerview:recyclerview:1.3.2")
//Retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
//Corrutinas
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/viewRoot"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.SearchView
android:id="@+id/svDogs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="7dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0"
app:queryHint="labrador, husky, no_existe"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvDogs"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/svDogs"/>
</androidx.constraintlayout.widget.ConstraintLayout>
DogsResponse.kt
data class DogsResponse (
@SerializedName("status") var status:String,
@SerializedName("message") var images: List<String>)
APIService.kt
interface APIService {
@GET
suspend fun getDogsByBreeds(@Url url: String): Response<DogsResponse>
}
item_dog.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="320dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="16dp"
android:elevation="7dp"
app:cardCornerRadius="8dp">
<ImageView
android:id="@+id/ivDog"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.cardview.widget.CardView>
DogViewHolder.kt
class DogViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val binding = ItemDogBinding.bind(view)
fun bind(image: String) {
Picasso.get().load(image).into(binding.ivDog)
}
}
DogAdapter.kt
class DogAdapter (private val images: List<String>) : RecyclerView.Adapter<DogViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DogViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return DogViewHolder(layoutInflater.inflate(R.layout.item_dog, parent, false))
}
override fun getItemCount(): Int {
return images.size
}
override fun onBindViewHolder(holder: DogViewHolder, position: Int) {
val item:String = images[position]
holder.bind(item)
}
}
MainActivity.kt
//androidx.appcompat.widget.SearchView
class MainActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private lateinit var binding: ActivityMainBinding
private lateinit var adapter: DogAdapter
private val dogImages = mutableListOf<String>()
companion object{
const private val WEB= "https://dog.ceo/api/breed/"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.svDogs.setOnQueryTextListener(this)
initRecyclerView()
}
private fun initRecyclerView() {
adapter = DogAdapter(dogImages)
// binding.rvDogs.setHasFixedSize(true)
binding.rvDogs.layoutManager = LinearLayoutManager(this)
binding.rvDogs.adapter = adapter
}
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(WEB)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
private fun searchByName(query: String) {
CoroutineScope(Dispatchers.IO).launch {
val call: Response<DogsResponse> = getRetrofit().create(APIService::class.java).getDogsByBreeds("$query/images")
val puppies:DogsResponse? = call.body()
runOnUiThread {
if (call.isSuccessful) {
val images:List<String> = puppies?.images ?: emptyList()
// show RecyclerView
dogImages.clear()
dogImages.addAll(images)
adapter.notifyDataSetChanged()
} else {
showErrorDialog()
}
hideKeyboard()
}
}
}
override fun onQueryTextSubmit(query: String): Boolean {
if (!query.isNullOrEmpty())
searchByName(query.lowercase())
return true
}
private fun showErrorDialog() {
Toast.makeText(this, "Ha ocurrido un error", Toast.LENGTH_SHORT).show()
}
override fun onQueryTextChange(newText: String?): Boolean {
return true
}
private fun hideKeyboard() {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.viewRoot.windowToken, 0)
}
}
Comprobación:
- Obtener fotos de una raza, por ejemplo labrador, husky, chihuahua
- Obtener fotos de una raza que no existe
Mejoras:
– Usar el patrón Singleton con Retrofit
– Tratamiento de errores en Retrofit
– Mostrar todas las razas y, al pulsar en una, obtener las fotos de esa raza
https://dog.ceo/api/breeds/list/all

Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.