Retrofit2 no Android usando Kotlin

Hoje consideraremos trabalhar com o Retrofit 2. Para o bem da verdade, deve-se notar que trabalharemos com mais 2 bibliotecas separadas, nomeadamente Picasso e Spots-dialog .



Recomendo a leitura deste artigo apenas para quem ainda não trabalhou com o Retrofit 2. Afinal, neste artigo vou descrever tudo com o máximo de detalhes possível para que todos entendam.



0. Criação do projeto



Tudo aqui é o mais simples possível, crie um novo projeto no Android Studio, selecione Atividade vazia. Em seguida, você precisa selecionar uma linguagem de programação, teremos Kotlin.



1. Adicionar dependências



Agora precisamos adicionar todas as bibliotecas necessárias, então vamos para build.gradle e adicionamos o seguinte:



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 você deve ter notado, aqui adicionamos todas as bibliotecas necessárias, incluindo a caixa de diálogo de progresso dos Pontos. Você pode ler mais sobre isso aqui. Então, em build.gradle (Modul: app), temos que inserir o seguinte:



 compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }


Resta apenas ir aos manifestos e adicionar permissão para usar o telefone
  <uses-permission android:name="android.permission.INTERNET"/>




2. Adicionar classes de dados



Antes de passar para o segundo ponto, precisamos descobrir de onde obter os dados? O Parse será a partir daqui.



Ótimo, então copie o conteúdo deste site e acesse aqui. Colamos aqui o texto anteriormente copiado do nosso site, depois de clicarmos na árvore, nos deram uma lista, abrimos, agora vemos que temos 8 objetos. Se alguém não entender, vou mostrar uma tela:







O que você vê à direita é o nosso texto, que copiamos e o que está à direita já são dados processados.



Agora vamos voltar ao Android Studio, criamos uma pasta, chamamos de Model, lá criamos uma classe kotlin e a nomeamos Movie de uma classe regular, transformamos a classe de dados, apenas adicionamos os dados antes da classe e substituímos as chaves por parênteses, então indicamos as variáveis ​​que já temos entre colchetes espionado no site, aliás as variáveis ​​devem ser do tipo anulável.



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
)




Se você está se perguntando por que a pasta se chama Model, direi que:



Model é a lógica associada aos dados do aplicativo. Em outras palavras, são POJOs, classes para trabalhar com uma API, um banco de dados.



3. Criação do cliente



Em seguida, criamos a pasta Retrofit, e na pasta criamos um objeto e o nomeamos RetrofitClient, então criamos uma variável de retrofit do tipo Retrofit, em seguida criamos uma função e chamamos de getCleint (baseUrl: String) e o tipo de retorno é Retrofit. No corpo da função, é necessário verificar se o retrofit é nulo e, se o retrofit for nulo, atribuímos Retrofit ao retrofit.Builder () anexar baseUrl com o parâmetro baseUrl, em seguida, anexar o método addconverterFactory com o parâmetro GsonConverterFactory.create () e construir usando o build ( ) e retornar o retrofit para um tipo diferente de zero



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!!
    }
}




O Builder no Retrofit é uma instância que usa a interface do Builder e a API para definir a definição do terminal de URL para operações HTTP



4. Trabalho com interface



Interface - necessária para criar classes abstratas.



Crie um pacote de interface nele, colocamos uma interface e chamamos de RetrofitServieces. Crie uma solicitação Get entre parênteses, escreva aspas, e entre aspas indica o branch do qual analisaremos os dados, isso é maravilhoso. Mas antes disso, vale a pena dizer o que uma solicitação GET e POST são

GET - solicita dados de um recurso específico (site)

POST - envia dados para o servidor para processamento adicional



Ok, agora você precisa criar uma função getMovieList, que deve retornar uma chamada do tipo MutableList, e uma MutableList deve ser Tipo de filme



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. Comum



Agora temos que criar a pasta Common, nesta pasta colocamos um objeto e chamamos de Common, criamos uma variável, chamamos de BASE_URL e nela temos que colocar o link do qual analisamos os dados, mas não colocamos o último branch, pois é dele que recebemos os dados ... Criamos a variável retrofitServices, ela tem um método get (), atribuímos RetrofitClient a ela e só então conectamos o método getClient em rede com o parâmetro RetrofitServices :: class.java para 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. Layout



Vá para activity_main.xml e adicione RecyclerView lá



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>




Na pasta de layout, crie um item_layout no elemento raiz, especifique o 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



Agora temos que criar um pacote de adaptadores, no qual colocamos uma classe e a chamamos de MyMovieAdapter. O

adaptador é responsável por recuperar dados de um conjunto de dados e por criar objetos de visualização com base nesses dados.



Na classe MyMovieAdapter, criamos variáveis ​​que estarão disponíveis apenas nesta classe private val movieList: MutableList do tipo Movie e especificaremos o tipo de valor de retorno, teremos RecyclerView.Adapter do tipo MyMovieAdapter.MyViewHolder



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

Criamos a classe MyViewHolder, nesta classe especificamos o parâmetro itemView: View e o tipo de retorno RecyclerView.ViewHolder e colocamos variáveis ​​no corpo desta classe, por exemplo:



val image: ImageView = itemView.image_movie image_movie é extraído de item_layout

e, portanto, especificamos todos os itens de visualização restantes.



Vamos criar uma função de ligação com o parâmetro listItem: Movie, aqui podemos tornar nossos itens de visualização clicáveis, acho que você pode fazer isso.



Em seguida, reescrevemos getItemCount () para substituir fun getItemCount () = movieList.size. Tudo é simples aqui, criamos uma função e retornamos movieList.size. Ótimo, tudo o que resta é lidar com onBindViewHolder e onCreateViewHolder



onCreateViewHolder - cria um novo objeto ViewHolder sempre que o RecyclerView precisa.



onBindViewHolder - pega um objeto ViewHolder e define os dados necessários para a linha correspondente no componente de visualização



Agora vamos analisar o caso com o tipo de retorno onCreateViewHolder MyViewHolder.

Crie a variável itemView, atribua-lhe LayoutInflater.from (parent.context) .inflate (R.layout.item_layout, parent, false) e retorne MyViewHolder com o parâmetro itemView. Agora vá para onBindViewHolder no corpo em que criamos a variável listItem: Movie e atribuímos movieList [position]. Em seguida, anexamos o método bind com os parâmetros listItem a holder'y. Em seguida, usamos a biblioteca de Picasso.



Picasso.get (). Load (movieList [position] .imageurl) .into (holder.image). Em seguida, adicione holder.txt_name.text = movieList [position] .name, e é assim que fazemos com todos os nossos elementos de visualização



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! Saiu um pouco. Vá para MainActivity para começar, vamos criar variáveis, e para não declará-las do tipo null, vamos declará-las através de lateinit var mService: RetrofitServices, precisamos criar mais 3 deles, a saber: LinearLayoutManager, MyMovieAdapter, AlertDialog. Você pode chamá-los do que quiser, não importa. No método onCreate, atribuímos Common.retrofitServices a RetrofitServices. Na próxima linha, anexamos setHasFixedSize (true) ao nosso recyclerView - graças a este método, podemos otimizar nossa lista, então atribuímos LinearLayoutManager (this) ao nosso layoutManager.



Gerente de Layout- este é o responsável pelo posicionamento dos componentes da View que não são mais visíveis ao usuário. Além disso, tudo é igualmente fácil de anexar à nossa lista layoutManager e já atribuir layoutManager a ela. Ok, agora trabalhando com a biblioteca SpotsDialog. especificamos a variável nomeada anteriormente com o tipo AlertDialog atribuímos SpotsDialog, anexamos o método Builder e, em seguida, anexamos o método setCancelablec com o parâmetro true, devemos anexar o método setContext com este parâmetro e anexar o método build.



Agora temos que criar uma nova função fora do método onCreate, chamada de função getAllMovieList. No corpo desta função, devemos especificar nosso diálogo e anexar o método show () a ele, em

seguida , adicionar o método getMovieList a mService .enqueue (objeto: Callback <MutableList> {)



Agora precisamos implementar métodos, temos dois deles onResponse e onFailure

e em onResponse, a saber, no corpo deste método, atribuímos a adapter'y



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


além disso, atribuímos o método notificationDataSetChanged () para adapter'y. Em nossa lista, anexamos adaptador e atribuímos adaptador. em seguida, atribuímos o método dispensar () ao diálogo. Isso significa que nosso diálogo desaparecerá depois que nossos dados forem carregados.



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! Neste artigo, aprendemos como trabalhar com Retrofit2 e colocá-lo em um RecyclerView.



All Articles