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.