Retrofit2 en Android usando Kotlin

Hoy consideraremos trabajar con Retrofit 2. En aras de la verdad, debe tenerse en cuenta que trabajaremos con 2 bibliotecas más separadas, a saber, Picasso y Spots-dialog .



Recomiendo este artículo para que lo lean solo aquellos que aún no han trabajado con Retrofit 2. Después de todo, en este artículo describiré todo con el mayor detalle posible para que todos lo entiendan.



0. Creación de proyectos



Todo aquí es lo más simple posible, cree un nuevo proyecto en Android Studio, seleccione Actividad vacía. A continuación, debe seleccionar un lenguaje de programación, lo tendremos Kotlin.



1. Agregar dependencias



Ahora necesitamos agregar todas las bibliotecas requeridas, así que vamos a build.gradle y agregamos lo siguiente:



dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    implementation 'com.squareup.picasso:picasso:2.71828'

    //noinspection GradleCompatible
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.github.d-max:spots-dialog:1.1@aar'
}


Como habrás notado, aquí hemos agregado todas las bibliotecas necesarias, incluido el cuadro de diálogo de progreso de Spots. Puedes leer más sobre esto aquí. Después de eso, en build.gradle (Modul: app), debemos insertar esto:



 compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }


Solo queda ir a los manifiestos y agregar permiso para usar el teléfono
  <uses-permission android:name="android.permission.INTERNET"/>




2. Agregar clases de datos



Antes de pasar al segundo punto, ¿necesitamos averiguar de dónde obtener los datos? Parse será de aquí.



Genial, entonces copie el contenido de este sitio y diríjase aquí. Aquí pegamos el texto previamente copiado de nuestro sitio, luego de hacer clic en el árbol, obtuvimos una lista, la abrimos, ahora vemos que tenemos 8 objetos. Si alguien no entiende, entonces les mostraré una pantalla:







Lo que ven a la derecha es nuestro texto que copiamos, y lo que a la derecha ya son datos procesados.



Ahora regresemos a Android Studio, creamos una carpeta, la llamamos Modelo, allí creamos una clase kotlin y la nombramos Movie de una clase regular, transformamos la clase de datos, solo agregamos datos antes de la clase, y reemplazamos las llaves con paréntesis, luego indicamos las variables que ya tenemos entre paréntesis espiado en el sitio, por cierto, las variables deben ser de tipo anulable.



Código completo
data class Movie(
    var name: String? = null,
    var realname: String? = null,
    var team: String? = null,
    var firstapperance: String? = null,
    var createdby: String? = null,
    var publisher: String? = null,
    var imageurl: String? = null,
    var bio: String? = null
)




Si se pregunta por qué la carpeta se llama Modelo, le diré que:



Modelo es la lógica asociada con los datos de la aplicación. En otras palabras, se trata de POJO, clases para trabajar con una API, una base de datos.



3. Creación de cliente



A continuación, creamos la carpeta Retrofit, y en la carpeta creamos un objeto y lo llamamos RetrofitClient, luego creamos una variable retrofit del tipo Retrofit, luego creamos una función y la llamamos getCleint (baseUrl: String) y el tipo de retorno es Retrofit. En el cuerpo de la función, es necesario verificar si la actualización es nula y si la actualización es nula, luego asignamos Retrofit a retrofit.Builder () adjuntamos baseUrl con el parámetro baseUrl, luego adjuntamos el método addconverterFactory con el parámetro GsonConverterFactory.create () y construimos usando el build ( ) y devolver la modificación a un tipo distinto de cero



Código completo

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClient {
    private var retrofit: Retrofit? = null

    fun getClient(baseUrl: String): Retrofit {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        }
        return retrofit!!
    }
}




El Builder en Retrofit es una instancia que usa la interfaz y la API del Builder para definir la definición del punto final de la URL para las operaciones HTTP.



4. Trabajar con la interfaz



Interfaz: necesaria para crear clases abstractas.



Creamos un paquete de interfaz en él, colocamos una interfaz y lo llamamos RetrofitServieces. Cree una solicitud Get entre paréntesis, escriba entre comillas y entre comillas indique la rama desde la que analizaremos los datos, esto es maravilloso. Pero antes de eso, vale la pena decir qué son una solicitud GET y POST

GET : solicita datos de un recurso específico (sitio)

POST : envía datos al servidor para su posterior procesamiento



Ok, ahora necesitamos crear una función getMovieList, que debería devolver una llamada de tipo MutableList, y una MutableList debería ser Tipo de película



Código completo

import com.example.retrofitmarvel.Model.Movie
import retrofit2.Call
import retrofit2.http.*

interface RetrofitServices {
    @GET("marvel")
    fun getMovieList(): Call<MutableList<Movie>>
}




5. Común



Ahora tenemos que crear la carpeta Common, en esta carpeta ponemos un objeto y lo llamamos Common, creamos una variable, lo llamamos BASE_URL y en ella debemos poner el enlace desde el que analizamos los datos, pero no ponemos la última rama, ya que es de ella que recibimos datos ... Creamos la variable retrofitServices, tiene un método get (), le asignamos RetrofitClient, y solo entonces conectamos el método getClient con el parámetro RetrofitServices :: class.java a RetrofitClient



Código completo

import com.example.retrofitmarvel.Interface.RetrofitServices
import com.example.retrofitmarvel.Retrofit.RetrofitClient

object Common {
    private val BASE_URL = "https://www.simplifiedcoding.net/demos/"
    val retrofitService: RetrofitServices
        get() = RetrofitClient.getClient(BASE_URL).create(RetrofitServices::class.java)
}




6. Disposición



Vaya a activity_main.xml y agregue RecyclerView allí



XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerMovieList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>




En la carpeta de diseño, cree un item_layout en el elemento raíz, especifique CardView



item_layout
<androidx.cardview.widget.CardView
    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="wrap_content"
    app:cardElevation="8dp"
    android:layout_margin="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="167dp">


        <ImageView
            android:id="@+id/image_movie"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/txt_name"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.238" />

        <TextView
            android:id="@+id/txt_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="192dp"
            android:layout_marginLeft="192dp"
            android:layout_marginTop="16dp"
            android:text="name"
            android:textColor="@android:color/black"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/txt_team"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="196dp"
            android:layout_marginLeft="196dp"
            android:layout_marginTop="8dp"
            android:text="team"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            android:textStyle="normal"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txt_name" />

        <TextView
            android:id="@+id/txt_createdby"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="184dp"
            android:layout_marginLeft="184dp"
            android:layout_marginTop="12dp"
            android:text="createdby"
            android:textColor="@android:color/black"
            android:textSize="18sp"
            android:textStyle="italic"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txt_team" />


    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>




7. Adaptador



Ahora tenemos que crear un paquete Adapter, en el que colocamos una clase y la llamamos MyMovieAdapter

Adapter es responsable de recuperar datos de un conjunto de datos y de crear objetos View basados ​​en estos datos.



En la clase MyMovieAdapter, creamos variables que estarán disponibles solo en esta clase private val movieList: MutableList de tipo Movie y especificamos el tipo de valor de retorno, lo tendremos RecyclerView.Adapter de tipo MyMovieAdapter.MyViewHolder



Implementar métodos, a saber onCreateViewHolder, getItemCount y onBindViewHolder

Creamos la clase MyViewHolder, en esta clase especificamos el parámetro itemView: View y el tipo de retorno RecyclerView.ViewHolder y ponemos variables en el cuerpo de esta clase, por ejemplo:



val image: ImageView = itemView.image_movie image_movie se extrae de item_layout

y, por lo tanto, especificamos todos los elementos de vista restantes.



Creemos una función de vinculación con un parámetro listItem: Movie, aquí podemos hacer que se pueda hacer clic en nuestros elementos de vista, creo que puede hacerlo.



A continuación, reescribimos getItemCount () para anular la diversión getItemCount () = movieList.size. Aquí todo es simple, creamos una función y devolvemos movieList.size. Genial, todo lo que queda es lidiar con onBindViewHolder y onCreateViewHolder



onCreateViewHolder : crea un nuevo objeto ViewHolder cada vez que RecyclerView lo necesita.



onBindViewHolder : toma un objeto ViewHolder y establece los datos necesarios para la línea correspondiente en el componente de vista



Ahora analizaremos el caso con el tipo de retorno onCreateViewHolder MyViewHolder.

Cree una variable itemView, asígnele LayoutInflater.from (parent.context) .inflate (R.layout.item_layout, parent, false) y devuelva MyViewHolder con el parámetro itemView. Ahora ve a onBindViewHolder en el cuerpo creamos la variable listItem: Movie y asignamos movieList [position]. A continuación, adjuntamos el método bind al holder'y con los parámetros listItem. A continuación, usamos la biblioteca Picasso.



Picasso.get (). Cargar (movieList [posición] .imageurl) .en (holder.image). Luego agregue holder.txt_name.text = movieList [position] .name, y así es como lo hacemos con todos nuestros elementos de vista



Código completo

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.retrofitmarvel.Model.Movie
import com.example.retrofitmarvel.R
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.item_layout.view.*

class MyMovieAdapter(private val context: Context,private val movieList: MutableList<Movie>):RecyclerView.Adapter<MyMovieAdapter.MyViewHolder>() {

    class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
        val image: ImageView = itemView.image_movie
        val txt_name: TextView = itemView.txt_name
        val txt_team: TextView = itemView.txt_team
        val txt_createdby: TextView = itemView.txt_createdby

        fun bind(listItem: Movie) {
            image.setOnClickListener {
                Toast.makeText(it.context, "  ${itemView.image_movie}", Toast.LENGTH_SHORT)
                    .show()
            }
            itemView.setOnClickListener {
                Toast.makeText(it.context, "  ${itemView.txt_name.text}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
        return MyViewHolder(itemView)
    }

    override fun getItemCount() = movieList.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val listItem = movieList[position]
        holder.bind(listItem)

        Picasso.get().load(movieList[position].imageurl).into(holder.image)
        holder.txt_name.text = movieList[position].name
        holder.txt_team.text = movieList[position].team
        holder.txt_createdby.text = movieList[position].createdby
    }

}





8. MainActivity



¡Excelente! Dejó solo un poquito. Vaya a MainActivity para empezar, crearemos variables, y para no declararlas de tipo null, las declararemos a través de lateinit var mService: RetrofitServices, necesitamos crear 3 más de estas, a saber: LinearLayoutManager, MyMovieAdapter, AlertDialog. Puedes llamarlos como quieras, no importa. En el método onCreate, asignamos Common.retrofitServices a RetrofitServices. En la siguiente línea, adjuntamos setHasFixedSize (true) a nuestro recyclerView; gracias a este método podemos optimizar nuestra lista, luego asignamos LinearLayoutManager (this) a nuestro layoutManager.



Administrador de diseño- esto es lo que se encarga del posicionamiento de los componentes de View que ya no son visibles para el usuario. Además, todo es tan fácil de adjuntar a nuestra lista layoutManager y ya asignar layoutManager a esto. Ok, ahora trabajando con la biblioteca SpotsDialog. especificamos la variable previamente nombrada con el tipo AlertDialog asignamos SpotsDialog adjuntamos el método Builder luego adjuntamos el método setCancelablec con el parámetro true a esto debemos adjuntar el método setContext con el parámetro this y adjuntar el método build.



Ahora tenemos que crear una nueva función fuera del método onCreate llamada función getAllMovieList. En el cuerpo de esta función, debemos especificar nuestro diálogo y adjuntarle el método show (),

luego agregar el método getMovieList a mService .enqueue (object: Callback <MutableList> {)



Ahora necesitamos implementar los métodos, tenemos dos de ellos onResponse y onFailure

y en onResponse, es decir, en el cuerpo de este método que asignamos a adapter'y



MyMovieAdapter(baseContext, response.body() as MutableList<Movie>)


además, asignamos el método notifyDataSetChanged () a adapter'y. A nuestra lista, adjuntamos adaptador y asignamos adaptador. luego asignamos el método desechar () al diálogo. Esto significa que nuestro diálogo desaparecerá después de que se carguen nuestros datos.



Código completo

import android.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.retrofitmarvel.Adapter.MyMovieAdapter
import com.example.retrofitmarvel.Common.Common
import com.example.retrofitmarvel.Interface.RetrofitServices
import com.example.retrofitmarvel.Model.Movie
import com.example.retrofitmarvel.R

import dmax.dialog.SpotsDialog
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class MainActivity : AppCompatActivity() {

    lateinit var mService: RetrofitServices
    lateinit var layoutManager: LinearLayoutManager
    lateinit var adapter: MyMovieAdapter
    lateinit var dialog: AlertDialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mService = Common.retrofitService
        recyclerMovieList.setHasFixedSize(true)
        layoutManager = LinearLayoutManager(this)
        recyclerMovieList.layoutManager = layoutManager
        dialog = SpotsDialog.Builder().setCancelable(true).setContext(this).build()

        getAllMovieList()
    }

    private fun getAllMovieList() {
        dialog.show()
        mService.getMovieList().enqueue(object : Callback<MutableList<Movie>> {
            override fun onFailure(call: Call<MutableList<Movie>>, t: Throwable) {

            }

            override fun onResponse(call: Call<MutableList<Movie>>, response: Response<MutableList<Movie>>) {
                adapter = MyMovieAdapter(baseContext, response.body() as MutableList<Movie>)
                adapter.notifyDataSetChanged()
                recyclerMovieList.adapter = adapter

                dialog.dismiss()
            }
        })
    }
}




¡Excelente! En este artículo, aprendimos cómo trabajar con Retrofit2 y ponerlo en un RecyclerView.



All Articles