Retrofit2 sur Android avec Kotlin

Aujourd'hui, nous allons envisager de travailler avec Retrofit 2. Par souci de vérité, il convient de noter que nous travaillerons avec 2 bibliothèques distinctes supplémentaires, à savoir Picasso et Spots-dialog .



Je recommande cet article à lire uniquement à ceux qui n'ont pas encore travaillé avec Retrofit 2. Après tout, dans cet article, je vais tout décrire avec le plus de détails possible afin que tout le monde comprenne.



0. Création de projet



Tout ici est aussi simple que possible, créez un nouveau projet dans Android Studio, sélectionnez Activité vide. Ensuite, vous devez sélectionner un langage de programmation, nous l'aurons Kotlin.



1. Ajouter des dépendances



Nous devons maintenant ajouter toutes les bibliothèques requises, nous allons donc dans build.gradle et ajoutons ce qui suit:



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


Comme vous l'avez peut-être remarqué, nous avons ajouté ici toutes les bibliothèques nécessaires, y compris la boîte de dialogue de progression Spots. Vous pouvez en savoir plus ici. Après cela, dans build.gradle (Modul: app), nous devons insérer ceci:



 compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }


Il ne reste plus qu'à accéder aux manifestes et à ajouter l'autorisation d'utiliser le téléphone
  <uses-permission android:name="android.permission.INTERNET"/>




2. Ajout de classes de données



Avant de passer au deuxième point, nous devons savoir d'où proviennent les données? Parse sera à partir d'ici.



Génial, alors copiez le contenu de ce site et allez ici. Ici, nous collons le texte précédemment copié de notre site, après avoir cliqué sur l'arbre, nous avons obtenu une liste, ouvrez-la, maintenant nous voyons que nous avons 8 objets. Si quelqu'un ne comprend pas, alors je vais vous montrer un écran:







Ce que vous voyez à droite est notre texte que nous avons copié, et ce qui à droite est déjà des données traitées.



Revenons maintenant à Android Studio, nous créons un dossier, nous l'appelons Model, là nous créons une classe kotlin et la nommons Movie à partir d'une classe régulière, nous transformons la classe de données, nous ajoutons simplement des données avant la classe, et remplaçons les accolades par des parenthèses, puis nous indiquons les variables que nous avons déjà entre parenthèses espionné sur le site, d'ailleurs les variables doivent être de type nullable.



Code complet
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 vous vous demandez pourquoi le dossier s'appelle Modèle, je vous dirai que: Le



modèle est la logique associée aux données d'application. En d'autres termes, ce sont des POJO, des classes pour travailler avec une API, une base de données.



3. Création du client



Ensuite, nous créons le dossier Retrofit, et dans le dossier, nous créons un objet et le nommons RetrofitClient, puis nous créons une variable de retrofit du type Retrofit, après cela nous créons une fonction et l'appelons getCleint (baseUrl: String) et le type de retour est Retrofit. Dans le corps de la fonction, il est nécessaire de vérifier la mise à niveau pour null et si la mise à niveau est nulle, alors nous affectons Retrofit à la retrofit.Builder () attachez baseUrl avec le paramètre baseUrl, puis attachez la méthode addconverterFactory avec le paramètre GsonConverterFactory.create () et construisez en utilisant le build ( ) et ramener la modernisation à un type différent de zéro



Code complet

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




Le générateur dans Retrofit est une instance qui utilise l'interface et l'API du générateur pour définir la définition du point de terminaison URL pour les opérations HTTP



4. Travailler avec l'interface



Interface - nécessaire pour créer des classes abstraites.



Créez un package d'interface, nous y mettons une interface et l'appelons RetrofitServieces. Créez une requête Get entre parenthèses, écrivez des guillemets, et entre guillemets indique la branche à partir de laquelle nous allons analyser les données, c'est merveilleux. Mais avant cela, il vaut la peine de dire ce qu'est une requête GET et POST

GET - demande des données à une ressource spécifique (site)

POST - envoie des données au serveur pour un traitement ultérieur



Ok, maintenant vous devez créer une fonction getMovieList, qui devrait retourner un appel de type MutableList, et une MutableList devrait Type de film



Code complet

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

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




5. Commun



Maintenant, nous devons créer le dossier Common, dans ce dossier, nous mettons un objet et l'appelons Common, créons une variable, l'appelons BASE_URL et nous devons y mettre le lien à partir duquel nous analysons les données, mais ne mettons pas la dernière branche, car c'est d'elle que nous recevons les données ... Nous créons la variable retrofitServices, elle a une méthode get (), nous lui assignons RetrofitClient, et alors seulement nous mettons en réseau la méthode getClient avec le paramètre RetrofitServices :: class.java à RetrofitClient



Code complet

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



Accédez à activity_main.xml et ajoutez RecyclerView ici



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>




Dans le dossier layout, créez un item_layout dans l'élément racine, spécifiez 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. Adaptateur



Nous devons maintenant créer un package Adapter, dans lequel nous mettons une classe et l'appelons MyMovieAdapter

Adapter est chargé de récupérer les données d'un ensemble de données et de créer des objets View basés sur ces données.



Dans la classe MyMovieAdapter, nous créons des variables qui ne seront disponibles que dans cette classe private val movieList: MutableList de type Movie et spécifions le type de valeur de retour, nous l'aurons RecyclerView.Adapter de type MyMovieAdapter.MyViewHolder



Implémenter des méthodes, à savoir onCreateViewHolder, getItemCount et onBindViewHolder

Nous créons la classe MyViewHolder, dans cette classe nous spécifions le paramètre itemView: View et le type de retour RecyclerView.ViewHolder et nous mettons des variables dans le corps de cette classe, par exemple:



val image: ImageView = itemView.image_movie image_movie est dessiné à partir de item_layout

et nous spécifions donc pour tous les éléments de vue restants.



Créons une fonction de liaison avec un paramètre listItem: Movie, ici nous pouvons rendre nos éléments de vue cliquables, je pense que vous pouvez le faire.



Ensuite, nous réécrivons getItemCount () pour remplacer fun getItemCount () = movieList.size. Tout est simple ici, nous avons créé une fonction et renvoyé movieList.size. Génial, il ne reste plus qu'à gérer onBindViewHolder et onCreateViewHolder



onCreateViewHolder - crée un nouvel objet ViewHolder chaque fois que RecyclerView en a besoin.



onBindViewHolder - prend un objet ViewHolder et définit les données nécessaires pour la ligne correspondante dans le composant de vue



Nous allons maintenant analyser le cas avec le type de retour onCreateViewHolder MyViewHolder.

Créez une variable itemView, affectez-la LayoutInflater.from (parent.context) .inflate (R.layout.item_layout, parent, false) et renvoyez MyViewHolder avec le paramètre itemView. Maintenant, allez à onBindViewHolder dans le corps, nous créons la variable listItem: Movie et assignons movieList [position]. Ensuite, nous attachons la méthode bind au holder'y avec les paramètres listItem. Ensuite, nous utilisons la bibliothèque Picasso.



Picasso.get (). Load (movieList [position] .imageurl) .into (holder.image). Ajoutez ensuite holder.txt_name.text = movieList [position] .name, et c'est ainsi que nous faisons avec tous nos éléments de vue



Code complet

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



Excellent! A gauche juste un peu. Allez dans MainActivity pour commencer, nous allons créer des variables, et afin de ne pas les déclarer de type null, nous les déclarerons via lateinit var mService: RetrofitServices, nous devons en créer 3 de plus, à savoir: LinearLayoutManager, MyMovieAdapter, AlertDialog. Vous pouvez les appeler comme vous voulez, peu importe. Dans la méthode onCreate, nous affectons Common.retrofitServices à RetrofitServices. Sur la ligne suivante, nous attachons setHasFixedSize (true) à notre recyclerView - grâce à cette méthode, nous pouvons optimiser notre liste, puis nous affectons LinearLayoutManager (this) à notre layoutManager.



Gestionnaire de mise en page- c'est la chose qui est responsable du positionnement des composants View qui ne sont plus visibles par l'utilisateur. De plus, tout est tout aussi facile à attacher à notre liste layoutManager et déjà assigner layoutManager à cela. Ok, je travaille maintenant avec la bibliothèque SpotsDialog. nous spécifions la variable précédemment nommée avec le type AlertDialog nous assignons SpotsDialog nous attachons la méthode Builder puis nous attachons la méthode setCancelablec avec le paramètre true à cela nous devons attacher la méthode setContext avec le paramètre this et attacher la méthode de construction.



Nous devons maintenant créer une nouvelle fonction en dehors de la méthode onCreate appelée la fonction getAllMovieList. Dans le corps de cette fonction, nous devons spécifier notre boîte de dialogue et y attacher la méthode show (),

puis ajouter la méthode getMovieList à mService .enqueue (object: Callback <MutableList> {)



Nous devons maintenant implémenter les méthodes, nous en avons deux onResponse et onFailure

et dans onResponse, à savoir dans le corps de cette méthode que nous attribuons à adapter'y



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


De plus, nous attribuons la méthode notifyDataSetChanged () à adapter'y. À notre liste, nous attachons un adaptateur et attribuons un adaptateur. puis nous attribuons la méthode licenciement () à dialog. Cela signifie que notre boîte de dialogue disparaîtra une fois nos données chargées.



Code complet

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()
            }
        })
    }
}




Excellent! Dans cet article, nous avons appris à travailler avec Retrofit2 et à le placer dans un RecyclerView.



All Articles