Uso de Retrofit 2.0 en Android

Desde la ultima actualización de esta librería desde la version 1,9 a la 2.0.0 han cambiado muchas cosa, pero por ahora empezaremos a explicar como funciona.

Como primer punto indicaremos las librerías a importar en gradle:

compile 'com.squareup.retrofit2:retrofit:2.0.0'

Ahora, además de importar la librería principal, se deberá importar las librerías de parser que convertirán nuestro objeto json/xml en un objeto java. Pueden ser una o más de las siguientes

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

Recuerden que siempre deben colocar el sufijo “:{version}” en este caso “:2.0.0”.

Personalmente, recomiendo Gson para json y simple XML para xml, debido que en el caso de Gson no necesitas nada adicional para hacer el parse.

Ahora que tenemos nuestras librerías importadas deberían quedar de la siguiente manera:

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:23.2.1'
  compile 'com.android.support:support-v4:23.2.1'
  compile 'com.squareup.retrofit2:retrofit:2.0.0'
  compile 'com.squareup.retrofit2:converter-gson:2.0.0' 
}

Ahora, lo siguiente que deberemos hacer es crear la interface necesaria para poder conectarnos al web service. Esta puede estar en un package o módulo diferente dependiendo de como tengas tu proyecto. Esta interfaz será instanciada por Retrofit para que nosotros llamemos al método que necesitemos. En este caso voy a crear la interfaz llamada NetworkInterfaz.

public interface NetworkInterfaces{
  //En la nueva version la url debe terminar con '/'
  String URL = "http://www.example.com/" 

  @POST("llamadaPost")
  Call<ResponsePost> hacerLlamada(@Body RequestPost);
}

En la interfaz anterior hemos declarado la url base a la cual nos conectaremos y el método al cual llamaremos cuando queramos hacer la llamada al web service. A continuación colocaré las expresiones json  de consulta y respuesta con sus respectivos objetos.

Json de Consulta:

{
  "nombre":"nombre Ejemplo",
  "consulta":"posición y gustos"
}

Json de Respuesta:

{
  "nombre":"Nombre Ejemplo",
  "pais":"Chile",
  "latLng:["lat":-33.4189513,"lng":-70.6010167],
  "gustos":["Programar", "Salir"]
}

Objeto de Consulta:

public class RequestPost{
  private String name;
  private String consulta;

  public RequestPost(){}

  public RequestPost(String name, String consulta){
    this.name = name;
    this.consulta = consulta;
  }

  public String getName(){
    return name;
  }

  public void setName(String name){
    this.name = name;
  }

  public String getConsulta(){
    return consulta;
  }

  public void setConsulta(String consulta){
    this.consulta = consulta;
  }
}

Objeto de Respuesta

public class ResponsePost{
  private String nombre;
  private String pais;
  private LatLng latLng;
  private String[] gustos;

  public ResponsePost(){}

  public ResponsePost(String nombre, String pais, LatLng latLng, String[] gustos){
    this.nombre = nombre;
    this.pais = pais;
    this.latLng = latLng;
    this.gustos = gustos;
  }

  public String getNombre(){
    return nombre;
  }

  public void setNombre(String nombre){
    this.nombre = nombre;
  }

  public String getPais(){
    return pais;
  }

  public void setPais(String pais){
    this.pais = pais;
  }

  public LatLng getLatLng(){
    return latLng;
  }

  public void setLatLng(LatLng latLng){
    this.latLng = latLng;
  }

  public String[] getGustos(){
    return gustos;
  }

  public void setGustos(String[] gustos){
    this.gustos = gustos;
  }

  public class LatLng{
    private float lat;
    private float lng;

    public LatLng(){}

    public LatLng(float lat, float lng){
      this.lat = lat;
      this.lng = lng;
    }

    public float getLat(){
      return lat;
    }

    public void setLat(float lat){
      this.lat = lat;
    }

    public float getLng(){
      return lng;
    }

    public void setLng(float lng){
      this.lng = lng;
    }
  }
}

En la clase de respuesta declaré un innerClass, que puede estar en otro archivo sin ningún problema. Ahora que tenemos los preparativos terminados crearemos la llamada al servicio Web.

//Declaramos nuestro objeto Retrofit y le indicamos el endpoint 
//y con que vamos a hacer el parse de la información finalizamos con build
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(NetworkInterfaces.URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
//Declaramos y llenamos nuestro objeto Request
RequestPost requestPost = new RequestPost("nombre Ejemplo","Posición y gustos");

//Declaramos la interfaz y dejamos que retrofit la instancie
NetworkInterfaces interfaces = retrofit.create(NetworkInterfaces.class);

//Hacemos el objeto tipo llamada 
Call<ResponsePost> responseCall = interfaces.hacerLlamada(requestPost);

//Hacemos la llamada asíncrona. En este caso declaré el callback dentro
//del mismo método. En lo personal me gusta crear una clase aparte
//o implementar la interfaz en la clase
responseCall.enqueue(new Callback<ResponsePost>{
  //Este método se llamará cuando se retorne del web service
  @Override
  public void onResponse(Call<ResponsePost> call, Response<ResponsePost> response){
    //Obtenemos nuestro objeto parseado, si hubo algún problema
    //la aplicación se caerá
    ResponsePost responsePost = response.body();
  }

  //Método llamado si existe algún problema en la llamada al websevice.
  @Override
  public void onFailure(Call<ResponsePost> call, Throwable t){}
});

Ahora veremos las diferentes variaciones en las llamadas:

1.- En las interfaces existen mas llamadas, entre las más usadas están:

a) @GET(“end point de conexión”)

Ejemplo:

@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost);

b) @Headers(“header que queramos agregar”)

Ejemplo:

@Headers("Content-Type:application/json")
@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost);

c) @Query Cuando se quieran agregar elementos a la url en la forma ?dato=valor

Ejemplo:

@Headers("Content-Type:application/json")
@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost, @QueryMap Map<String,String> options);

d) @QueryMap Cuando se quieran agregar multiples elementos a la url en la forma ?dato=valor

Ejemplo:

@Headers("Content-Type:application/json")
@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost, @Query("key_query")String llamadaUrl);

e) @Header(“keyHeader”) Cuando se quieran agregar headers de manera dinámica.

Ejemplo:

@Headers("Content-Type:application/json")
@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost, @Query("key_query")String llamadaUrl, @Header("header")String valor);

f) @Path: Cuando quieras cambiar algo del endpoint de manera dinámica.

 Ejemplo:

@Headers("Content-Type:application/json")
@GET("llamadaPost")
Call<ResponsePost> hacerLlamada(@Body RequestPost, @Query("key_query")String llamadaUrl, @Header("header")String valor, @Path("path_a_modificar")String path);

Con esto ya tenemos las llamadas al servicio web de una manera rápida y simple.

El código de ejemplo está disponible en el repositorio oficial de la comunidad.

Comenta este post