Android Retrofit Library Example – continue




This post is next steps of previous post. I strongly recommend to go through previous post before you proceed 🙂
We have already seen how to use android retrofit library to send request to rest based web services. Also, We had shown output in logcat. In this tutorial, We will see how to show the response coming from server in RecyclerView. After that, we will see some advance concept about retrofit library.

Output

tutorialwing android retrofit library exmaple

Response from server shown in Recycleview

Video Output

Source Code

Getting started

There are 2 sections in this tutorial.
a. Show Server Response in RecyclerView.
b. Retrofit advance concepts.

1. Show Server Response in RecyclerView

In this section, we will show response coming from server in previous tutorial to RecyclerView.

1.1 Project Structure

I have created a new package named adapter that contains adapter for RecyclerView. Also, there is a new xml file question_item.xml. Don’t worry about this new stuff. We will go through it one by one 🙂 . Finally, our project structure will be like below.

android retrofit library example

Tutorialwing – retrofit library example project structure

1.2 Add gradle for RecycleView in app/build.gradle

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

    compile 'com.android.support:recyclerview-v7:23.3.0'
}

1.3 Add RecyclerView in activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".activity.MainActivity">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/questionListRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
</RelativeLayout>

1.4 Create layout for a single item in RecyclerView

Create a new xml file question_item.xml in res/layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">


    <TextView
        android:id="@+id/positionNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/link"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@android:color/darker_gray"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"/>

</LinearLayout>

1.5 Create an adapter for RecyclerView

Create a new package adapter in tutorialwing.com.retrofitlibrary. Then, create a class QuestionAdapter for RecyclerView and add the code below in it.

package tutorialwing.com.retrofitlibrary.adapter;

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 java.util.List;

import tutorialwing.com.retrofitlibrary.R;
import tutorialwing.com.retrofitlibrary.model.Question;

public class QuestionAdapter extends RecyclerView.Adapter<QuestionAdapter.QuestionViewHolder> {

	private List<Question> questions;
	private int rowLayout;
	private Context context;


	public QuestionAdapter(List<Question> questions, int rowLayout, Context context) {
		this.questions = questions;
		this.rowLayout = rowLayout;
		this.context = context;
	}

	@Override
	public QuestionAdapter.QuestionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
		View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
		return new QuestionViewHolder(view);
	}


	@Override
	public void onBindViewHolder(QuestionViewHolder holder, final int position) {
		holder.positionNumber.setText("Question number : " + String.valueOf(position + 1));
		holder.questionTitle.setText("Title : " + questions.get(position).getTitle());
		holder.link.setText("Link : " + questions.get(position).getLink());
	}

	@Override
	public int getItemCount() {
		return questions.size();
	}

	public static class QuestionViewHolder extends RecyclerView.ViewHolder {
		TextView positionNumber;
		TextView questionTitle;
		TextView link;

		public QuestionViewHolder(View v) {
			super(v);
			positionNumber = (TextView) v.findViewById(R.id.positionNumber);
			questionTitle = (TextView) v.findViewById(R.id.title);
			link = (TextView) v.findViewById(R.id.link);
		}
	}
}

1.6 Show the Server Response in MainActivity

In MainActivity.java class, Add the code to fetch the data from server. Then, show the response in RecyclerView.

package tutorialwing.com.retrofitlibrary.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
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;
import tutorialwing.com.retrofitlibrary.R;
import tutorialwing.com.retrofitlibrary.adapter.QuestionAdapter;
import tutorialwing.com.retrofitlibrary.model.Question;
import tutorialwing.com.retrofitlibrary.model.QuestionList;
import tutorialwing.com.retrofitlibrary.rest.QuestionAPIService;
import tutorialwing.com.retrofitlibrary.rest.RestClient;

public class MainActivity extends AppCompatActivity {

	private static final String TAG = MainActivity.class.getSimpleName();

	QuestionAPIService apiService;

	RecyclerView recyclerView;
	QuestionAdapter adapter;
	List<Question> questions = new ArrayList<>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		apiService = RestClient.getClient().create(QuestionAPIService.class);

		recyclerView = (RecyclerView) findViewById(R.id.questionListRecyclerView);
		recyclerView.setLayoutManager(new LinearLayoutManager(this));

		adapter = new QuestionAdapter(questions, R.layout.question_item, getApplicationContext());
		recyclerView.setAdapter(adapter);

		fetchQuetionList();
	}

	private void fetchQuetionList() {
		Call<QuestionList> call = apiService.fetchQuestions("android");
		call.enqueue(new Callback<QuestionList>() {
			@Override
			public void onResponse(Call<QuestionList> call, Response<QuestionList> response) {
				Log.d(TAG, "Total number of questions fetched : " + response.body().getQuestions().size());

				questions.addAll(response.body().getQuestions());
				adapter.notifyDataSetChanged();
			}

			@Override
			public void onFailure(Call<QuestionList> call, Throwable t) {
				Log.e(TAG, "Got error : " + t.getLocalizedMessage());
			}
		});
	}
}

1.7 Output

If you have followed the tutorial properly, you will get the output as shown above. However, you can download the source code from link given above.




2. Retrofit Advance Concepts

While defining APIService interface, we use different annotations.These annotations define how a request will be handled. For example – If you are using @GET annotation, then, Get request will be processed. If you are using @POST annotation, then, POST request will be processed.
Also, Every method must contain HTTP annotation that provides the request method and relative URL(end url). There are five built-in annotations: GET, POST, PUT, DELETE, and HEAD.

2.1 GET Annotation

@GET("end url")
Call<QuestionList> getQuestionList(@Query("tagged") String tags);

2.2 POST Annotation

@POST("end url")
Call<Question> postQuestion(@Body Question question);

2.3 PUT Annotation

@PUT("end url")
Call<QuestionList> putQuestion(@Path("question_id") String questionId, @Body QuestionRequestBody question);

2.4 DELETE Annotation

@DELETE("end url")
Call<Question> deleteQuestion(@Path("id") int questionId);

2.5 HEADER Annotation

This is used when you want to send some data in header with request. For example, to send clientToken in header of the request etc.

Retrofit provides 2 ways to define header fields – static and dynamic. Static headers can not be changed for each request. It will be fixed for every request. On the other hand, Dynamic headers must be set for each request.

2.5.1 Static headers

If you want to pass only one key-value pair, you can pass it as below.

@Headers("Cache-Control: max-age=640000")
@GET("end url")
Call<QuestionList> getQuestionList(@Query("tagged") String tags);

If you want to pass multiple key-value pair, then, you can pass it as below.

@Headers({
        "Accept: application/vnd.yourapi.v1.full+json",
        "User-Agent: Your-App-Name"
    })
@GET("end url")
Call<QuestionList> getQuestionList(@Query("tagged") String tags);

Additionally, you can also define headers in intercept method in RequestInterceptor.

package tutorialwing.com.retrofitlibrary.rest;

import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RestClient {

	public static final String BASE_URL = "https://api.stackexchange.com";
	private static Retrofit retrofit = null;


	public static Retrofit getClient() {
		if (retrofit == null) {
			OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
			httpClient.addInterceptor(new Interceptor() {
				@Override
				public Response intercept(Interceptor.Chain chain) throws IOException {
					Request originalRequest = chain.request();

					Request request = originalRequest.newBuilder()
							.header("User-Agent", "Your-App-Name")
							.header("Accept", "application/vnd.yourapi.v1.full+json")
							.method(originalRequest.method(), originalRequest.body())
							.build();

					return chain.proceed(request);
				}
			});
			OkHttpClient client = httpClient.build();

			retrofit = new Retrofit.Builder()
					.baseUrl(BASE_URL)
					.addConverterFactory(GsonConverterFactory.create())
					.client(client)
					.build();
		}
		return retrofit;
	}
}
2.5.2 Dynamic headers

you can set headers dynamically as well. It is passed like a parameter in the header with @Header annotation.

@GET("end url")
Call<QuestionList> getQuestionList(@Header("Content-Range") String contentRange, @Query("tagged") String tags);



Conclusion

Retrofit is a simple, easy to learn and use, yet powerful android library for rest based web services.You can make synchronous as well as asynchronous calls through it. You can easily send request like GET,POST,PUT, DELETE using this library. Hope this tutorial helped you.

Support Us

If you have any suggestion about this post, please comment below. We are looking for someone who helps use to make our tutorial better. Also, If you want tutorials on any topic, you can mail us at tutorialwing@gmail.com. We will try to cover the topic as soon as possible. Connect with us on Facebook, Google+, Twitter and Youtube for more updates.