Retrofit Android Tutorial with Recyclerview
Advantages of retrofit
Retrofit is dead-simple to use. It essentially lets you treat API calls as simple Java method calls, so you only define which URLs to hit and the types of the request/response parameters as Java classes. The entire network call + JSON/XML parsing is completely handled by it (with help from Gson for JSON parsing), along with support for arbitrary formats with pluggable serialization/deserialization.Speed:
Compare with Volley and AsyncTask, Retrofit providing the very fast response to the request.
Let's get into the code part,
First, We have to add the retrofit dependency into our build.grade file. We can find the latest retrofit version in the official retrofit website. http://square.github.io/retrofit/
compile 'com.squareup.retrofit2:retrofit:2.3.0'
And the gson converter from retrofit used to convert the JSON response from the server.
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
Create the Retrofit instance
We need to create the Retrofit instance to send the network requests. we need to use the Retrofit Builder class and specify the base URL for the service.ApiClient.java package com.example.velm.retrofitexample; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class ApiClient { public static String BASE_URL ="http://10.0.2.2:3000/api/"; private static Retrofit retrofit; public static Retrofit getClient(){ if(retrofit == null){ retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } }
Setting Up the Retrofit Interface
Retrofit provides the list of annotations for each HTTP methods:@GET, @POST, @PUT, @DELETE, @PATCH or @HEAD.
The endpoints are defined inside of an interface using retrofit annotations to encode details about the parameters and request method. T return value is always a parameterized Call<T>.
Because the POJO classes are wrapped into a typed Retrofit Call class.
Method Parameters :
@Body – Sends Java objects as the request body.
@Url – use dynamic URLs.
@Query – We can simply add a method parameter with @Query() and a query parameter name, describing the type. To URL encode a query using the form:
@Query(value = "auth_token",encoded = true) String auth_token
ApiInterface.java package com.example.velm.retrofitexample; import java.util.List; import retrofit2.Call; import retrofit2.http.GET; public interface ApiInterface { @GET("movies/") Call<List<Movie>> getMovies(); }
Creating Model Class Before creating the model, we need to know what type of response we will be receiving.
http://localhost:3000/api/movies/ [ { "name":"Titanic", "year":"1997", "Director":"James Cameron" }, { "name":"Ghost in the Shell", "year":"2017", "Director":"Rupert Sanders" }, { "name":"Security", "year":"2017", "Director":"Alain Desrochers" }, { "name":"Gifted", "year":"2017", "Director":"Marc Webb" } ]
In my JSON response, I am having the list of movies with name, year and director properties. So, My Model class will be like Movie as class name and name, year, director are properties.|
Movie.java package com.example.velm.retrofitexample; import com.google.gson.annotations.SerializedName; public class Movie { @SerializedName("name") private String name; @SerializedName("year") private String year; @SerializedName("actor") private String actor; public Movie(String name, String year, String actor) { this.name = name; this.year = year; this.actor = actor; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getActor() { return actor; } public void setActor(String actor) { this.actor = actor; } @Override public String toString() { return "Movie{" + "name='" + name + '\'' + ", year='" + year + '\'' + ", actor='" + actor + '\'' + '}'; } }
Consume the REST web service
All the setup are done. Now we are ready to consume the REST web service. In Our MainActivity.Java, First, need to initialize the ApiClient.ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
After the initialization, we to call the getMovies() interface and implement the CallBacks. Part of the Implementation we need to override the onResponse() and onFailure().
If the request succeeds the callback will come into onResponse(). If any error in the request the callback will go into onFailure() method. In onResponse() method, we can get our response from response body.
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<List<Movie>> call = apiService.getMovies(); call.enqueue(new Callback<List<Movie>>() { @Override public void onResponse(Call<List<Movie>> call, Response<List<Movie>> response) { movieList = response.body(); Log.d("TAG","Response = "+movieList); } @Override public void onFailure(Call<List<Movie>> call, Throwable t) { Log.d("TAG","Failed = "+t.toString()); } });
Setup Recyclerview
adding the recyclerview dependency into our build.grade file.compile 'com.android.support:recyclerview-v7:26.0.+' Please check my Recyclerview tutorial for more details about recyclerview. Create the recyclerview
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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="com.example.velm.retrofitexample.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
create therecyclerview adapter
RecyclerAdapter.java package com.example.velm.retrofitexample; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import org.w3c.dom.Text; import java.util.List; public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyviewHolder> { Context context; List<Movie> movieList; public RecyclerAdapter(Context context, List<Movie> movieList) { this.context = context; this.movieList = movieList; } @Override public RecyclerAdapter.MyviewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.recycler_layout,parent,false); return new MyviewHolder(view); } @Override public void onBindViewHolder(RecyclerAdapter.MyviewHolder holder, int position) { holder.tvMovieName.setText(movieList.get(position).getName()); } @Override public int getItemCount() { return movieList.size(); } public class MyviewHolder extends RecyclerView.ViewHolder { TextView tvMovieName; public MyviewHolder(View itemView) { super(itemView); tvMovieName = (TextView)itemView.findViewById(R.id.textViewMovieName); } } }
recycler_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/textViewMovieName" android:layout_width="match_parent" android:layout_height="50dp" android:padding="5dp" android:gravity="center_vertical" android:textColor="@color/cardview_dark_background" android:layout_weight="1" android:text="TextView" /> </LinearLayout>
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<List<Movie>> call = apiService.getMovies(); call.enqueue(new Callback<List<Movie>>() { @Override public void onResponse(Call<List<Movie>> call, Response<List<Movie>> response) { movieList = response.body(); Log.d("TAG","Response = "+movieList); recyclerAdapter = new RecyclerAdapter(getApplicationContext(),movieList); recyclerView.setAdapter(recyclerAdapter); } @Override public void onFailure(Call<List<Movie>> call, Throwable t) { Log.d("TAG","Response = "+t.toString()); } });
MainActivity.java package com.example.velm.retrofitexample; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity { List<Movie> movieList; RecyclerView recyclerView; RecyclerAdapter recyclerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); movieList = new ArrayList<>(); recyclerView = (RecyclerView)findViewById(R.id.recyclerview); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<List<Movie>> call = apiService.getMovies(); call.enqueue(new Callback<List<Movie>>() { @Override public void onResponse(Call<List<Movie>> call, Response<List<Movie>> response) { movieList = response.body(); Log.d("TAG","Response = "+movieList); recyclerAdapter = new RecyclerAdapter(getApplicationContext(),movieList); recyclerView.setAdapter(recyclerAdapter); } @Override public void onFailure(Call<List<Movie>> call, Throwable t) { Log.d("TAG","Response = "+t.toString()); } }); } }