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.