In this android volley tutorial, we’ll be implementing the Volley library in our application. If you aren’t aware of the features of Volley, we recommend you to read this article before proceeding ahead.
Table of Contents
Android Volley
Network Requests in a Volley are added to a RequestQueue
. Instead of creating a new instance of RequestQueue every time, we follow the singleton pattern by creating a single instance of RequestQueue throughout our application.
In the application below, we’ll be implementing GET and POST StringRequest
and JsonObjectRequests
. We’ll use Gson library to parse the response and display the results in a RecyclerView.
Furthermore, we’ll implement a CustomRequest and load images from a URL in the ImageView.
Android Volley Tutorial Project Structure
Android Volley Gradle Dependencies
Before we get onto the coding aspect of this tutorial, add the following dependencies in your build.gradle
file.
compile 'com.android.support:cardview-v7:26.1.0'
compile 'com.android.support:recyclerview-v7:26.1.0'
compile 'com.android.support:design:26.1.0'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.android.volley:volley:1.0.0'
Android Volley Example Code
Layout – activity_main.xml
The code for the activity_main.xml
layout that holds the UI for the MainActivity.java
is given below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.journaldev.volley.RecyclerViewActivity">
<Button
android:id="@+id/btnImageLoader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/networkImageView"
android:layout_alignStart="@+id/networkImageView"
android:layout_below="@+id/networkImageView"
android:layout_marginTop="16dp"
android:text="LOAD IMAGE" />
<Button
android:id="@+id/btnImageRequest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btnImageLoader"
android:layout_alignBottom="@+id/btnImageLoader"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toEndOf="@+id/imageView"
android:layout_toRightOf="@+id/imageView"
android:text="IMAGE REQUEST" />
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/networkImageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_below="@+id/imageView"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/btnGET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/btnPOST"
android:layout_alignLeft="@+id/btnPOST"
android:layout_alignRight="@+id/btnPOST"
android:layout_alignStart="@+id/btnPOST"
android:layout_centerVertical="true"
android:text="GET String JSON" />
<Button
android:id="@+id/btnPOST"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnGET"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="POST String JSON" />
<Button
android:id="@+id/btnCustomRequest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/btnPOST"
android:layout_alignLeft="@+id/btnPOST"
android:layout_alignRight="@+id/btnPOST"
android:layout_alignStart="@+id/btnPOST"
android:layout_below="@+id/btnPOST"
android:layout_marginTop="8dp"
android:text="CUSTOM REQUEST" />
</RelativeLayout>
SingletonRequestQueue.java
package com.journaldev.volley;
import android.content.Context;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
public class SingletonRequestQueue {
private static SingletonRequestQueue mInstance;
private Context mContext;
private RequestQueue mRequestQueue;
private SingletonRequestQueue(Context context) {
mContext = context;
mRequestQueue = getRequestQueue();
}
public static synchronized SingletonRequestQueue getInstance(Context context) {
if (mInstance == null) {
mInstance = new SingletonRequestQueue(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mContext);
}
return mRequestQueue;
}
}
getInstance()
and getRequestQueue()
methods create an instance of SingletonRequestQueue and RequestQueue respectively for the first time and re-use it everywhere.
Linking the layout to the MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btnGET, btnPOST, btnImageLoader, btnCustomRequest, btnImageRequest;
NetworkImageView networkImageView;
ImageView imageView;
ArrayList<UserList.UserDataList> mUserDataList = new ArrayList<>();
String BASE_URL = "https://reqres.in";
String IMAGE_URL = "https://www.android.com/static/2016/img/share/oreo-lg.jpg";
int numberOfRequestsCompleted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGET = findViewById(R.id.btnGET);
btnPOST = findViewById(R.id.btnPOST);
btnImageLoader = findViewById(R.id.btnImageLoader);
btnImageRequest = findViewById(R.id.btnImageRequest);
btnCustomRequest = findViewById(R.id.btnCustomRequest);
networkImageView = findViewById(R.id.networkImageView);
imageView = findViewById(R.id.imageView);
btnGET.setOnClickListener(this);
btnPOST.setOnClickListener(this);
btnImageLoader.setOnClickListener(this);
btnCustomRequest.setOnClickListener(this);
btnImageRequest.setOnClickListener(this);
networkImageView.setDefaultImageResId(R.mipmap.ic_launcher);
networkImageView.setErrorImageResId(R.drawable.ic_error);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnGET:
GETStringAndJSONRequest("2", "4");
break;
case R.id.btnPOST:
POSTStringAndJSONRequest();
case R.id.btnImageLoader:
imageLoader();
case R.id.btnImageRequest:
imageRequest();
case R.id.btnCustomRequest:
customRequest();
break;
}
}
}
There are 5 buttons for GET, POST, ImageLoader, ImageRequest, CustomRequest processing. Each of the features are triggered in the onClickListener separately.
We’ll look at each of the methods separately
GETStringAndJSONRequest()
POSTStringAndJSONRequest()
imageLoader()
imageRequest()
customRequest()
We’ll be using the REST API available at www.reqres.in.
The UserList.java
class is the POJO class for serialising the response using Gson.
UserList.java
package com.journaldev.volley;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
public class UserList implements Serializable {
@SerializedName("page")
public Integer page;
@SerializedName("per_page")
public Integer perPage;
@SerializedName("total")
public Integer total;
@SerializedName("total_pages")
public Integer totalPages;
@SerializedName("data")
public List<UserDataList> userDataList;
public class UserDataList implements Serializable {
@SerializedName("id")
public Integer id;
@SerializedName("first_name")
public String first_name;
@SerializedName("last_name")
public String last_name;
@SerializedName("avatar")
public String avatar;
}
}
The above class implements Serializable
since an instance of it would passed as Bundle in Intents
Let’s look at the methods triggered by the Button click in the MainActivity.java
that encapsulate a Volley Request.
GETStringAndJSONRequest()
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (error instanceof NetworkError) {
Toast.makeText(getApplicationContext(), "No network available", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_LONG).show();
}
}
};
private void GETStringAndJSONRequest(String page_1, String page_2) {
mUserDataList.clear();
numberOfRequestsCompleted = 0;
VolleyLog.DEBUG = true;
RequestQueue queue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
String uri_page_one = String.format(BASE_URL + "/api/users?page=%1$s", page_1);
final String uri_page_two = String.format(BASE_URL + "/api/users?page=%1$s", page_2);
StringRequest stringRequest = new StringRequest(Request.Method.GET, uri_page_one, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response, "utf-8");
GsonBuilder builder = new GsonBuilder();
Gson mGson = builder.create();
UserList userList = mGson.fromJson(response, UserList.class);
mUserDataList.addAll(userList.userDataList);
++numberOfRequestsCompleted;
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.LOW;
}
};
queue.add(stringRequest);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(uri_page_two, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.wtf(response.toString(), "utf-8");
GsonBuilder builder = new GsonBuilder();
Gson mGson = builder.create();
UserList userList = mGson.fromJson(response.toString(), UserList.class);
mUserDataList.addAll(userList.userDataList);
++numberOfRequestsCompleted;
}
}, errorListener) {
@Override
public String getBodyContentType() {
return "application/json";
}
@Override
public Priority getPriority() {
return Priority.IMMEDIATE;
}
};
queue.add(jsonObjectRequest);
queue.addRequestFinishedListener(new RequestQueue.RequestFinishedListener<Object>() {
@Override
public void onRequestFinished(Request<Object> request) {
try {
if (request.getCacheEntry() != null) {
String cacheValue = new String(request.getCacheEntry().data, "UTF-8");
VolleyLog.d(request.getCacheKey() + " " + cacheValue);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (numberOfRequestsCompleted == 2) {
numberOfRequestsCompleted = 0;
startActivity(new Intent(MainActivity.this, RecyclerViewActivity.class).putExtra("users", mUserDataList));
}
}
});
}
Important points to note in the above code:
- We’ve created an instance of ErrorListener that’ll be used throughout the Activity.
- We’ve chained two requests in the RequestQueue.
- The first Request is a StringRequest.
page
acts as a URL encoded parameter in the API/api/users?
. The response is a JSONObject that’s serialized with Gson. We’ve set the priority of the StringRequest to low. Thus, this request should finish at last(in cases when the response from the server is quick, the priority won’t work). - The second Request is a JsonObjectRequest. Since it is a GET request, we’ve set the request body as null(check the second parameter). Priority is set to Immediate. Thus the JsonObjectRequest should complete first.
- We join the Lists returned from both the requests in
mUserDataList
ArrayList. - Inside the
addRequestFinishedListener
callback listener, we check if both the requests are over(by checking thenumberOfRequestsCompleted
counter. - Besides, inside
addRequestFinishedListener
callback, we can retrieve the response from theCache.Entry
- Try setting
setShouldCache()
to false on the Requests and you find the response in the cache. - Finally the user data list retrieved from both the requests is passed to the
RecyclerViewActivity.java
. This is where we’ll populate the ArrayList in a RecyclerView.
Let’s look at the RecyclerViewActivity
and layout code.
Layout – activity_recyclerview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.journaldev.volley.RecyclerViewActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
RecyclerViewActivity.java
package com.journaldev.volley;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerViewActivity extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
ArrayList userDataLists = (ArrayList) getIntent().getSerializableExtra("users");
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, userDataLists);
recyclerView.setAdapter(adapter);
}
}
The layout for each RecyclerView row is defined in recyclerview_row.xml.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="60dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/imgNetwork"
android:layout_width="48dp"
android:layout_centerVertical="true"
android:layout_height="48dp" />
<TextView
android:id="@+id/txtLabel"
android:layout_toRightOf="@+id/imgNetwork"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:gravity="center" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
RecyclerViewAdapter.java
package com.journaldev.volley;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.CustomRecyclerView> {
private List<UserList.UserDataList> itemList;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
public RecyclerViewAdapter(Context context, List<UserList.UserDataList> itemList) {
this.itemList = itemList;
mRequestQueue = SingletonRequestQueue.getInstance(context).getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> mCache = new LruCache<>(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
}
@Override
public CustomRecyclerView onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_row, null);
CustomRecyclerView rcv = new CustomRecyclerView(layoutView);
return rcv;
}
@Override
public void onBindViewHolder(CustomRecyclerView holder, int position) {
UserList.UserDataList myData = itemList.get(position);
holder.txtLabel.setText(myData.first_name + " " + myData.last_name);
holder.avatar.setImageUrl(myData.avatar, mImageLoader);
}
@Override
public int getItemCount() {
return this.itemList.size();
}
public class CustomRecyclerView extends RecyclerView.ViewHolder {
TextView txtLabel;
NetworkImageView avatar;
CustomRecyclerView(View itemView) {
super(itemView);
txtLabel = itemView.findViewById(R.id.txtLabel);
avatar = itemView.findViewById(R.id.imgNetwork);
}
}
}
We’ve initialized an ImageLoader that’ll display the Image from the URL in the NetworkImageView for each row.
The LRU cache is used for caching the image by implementing an ImageCache
. The argument inside the LruCache constructor is the number of cache entries limit.
POSTStringAndJSONRequest()
This method would chain multiple POST requests in a RequestQueue.
private void POSTStringAndJSONRequest() {
RequestQueue queue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
VolleyLog.DEBUG = true;
String uri = BASE_URL + "/api/users";
StringRequest stringRequest = new StringRequest(Request.Method.POST, uri, new Response.Listener() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response, "utf-8");
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.LOW;
}
@Override
public Map getParams() {
Map params = new HashMap();
params.put("name", "Anupam");
params.put("job", "Android Developer");
return params;
}
@Override
public Map getHeaders() throws AuthFailureError {
HashMap headers = new HashMap();
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
return headers;
}
};
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", "JournalDev.com");
jsonObject.put("job", "To teach you the best");
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(uri, jsonObject, new Response.Listener() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.wtf(response.toString(), "utf-8");
Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public int getMethod() {
return Method.POST;
}
@Override
public Priority getPriority() {
return Priority.NORMAL;
}
};
StringRequest stringRequestPOSTJSON = new StringRequest(Request.Method.POST, uri, new Response.Listener() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response);
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.HIGH;
}
@Override
public Map getHeaders() throws AuthFailureError {
HashMap headers = new HashMap();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", "Android Tutorials");
jsonObject.put("job", "To implement Volley in an Android Application.");
} catch (JSONException e) {
e.printStackTrace();
}
String requestBody = jsonObject.toString();
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
};
queue.add(stringRequest);
queue.add(jsonObjectRequest);
queue.add(stringRequestPOSTJSON);
}
- stringRequest – To POST parameters in a StringRequest, we need to override
getParams()
and pass the parameters as a key value pair. - jsonObjectRequest – To POST parameters in a JsonObjectRequest we pass the parameters inside a JSONObject and set them in the second parameter of the constructor.
- stringRequestPOSTJSON – To POST a JSON request body in a StringRequest, we override the method
getBody()
.
imageLoader()
private void imageLoader() {
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
ImageLoader imageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
private final LruCache mCache = new LruCache(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
networkImageView.setImageUrl(IMAGE_URL, imageLoader);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(
networkImageView, R.mipmap.ic_launcher, R.drawable.ic_error));
}
getImageListener()
handles the functionality of showing a default image until the network response is received, at which point it will switch to either the actual image or the error image.
The arguments passed inside the listener are the view’s instance, default image drawable, error image drawable.
imageRequest()
private void imageRequest() {
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
ImageRequest imageRequest = new ImageRequest(IMAGE_URL, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
if (response != null) {
imageView.setImageBitmap(response);
}
}
}, 200, 200, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, errorListener);
mRequestQueue.add(imageRequest);
}
customRequest()
private void customRequest() {
mUserDataList.clear();
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
String url = String.format(BASE_URL + "/api/users?page=%1$s", "2");
HashMap headers = new HashMap();
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
GsonRequest gsonRequest = new GsonRequest(url, UserList.class, headers, new Response.Listener() {
@Override
public void onResponse(UserList response) {
mUserDataList.addAll(response.userDataList);
startActivity(new Intent(MainActivity.this, RecyclerViewActivity.class).putExtra("users", mUserDataList));
}
}, errorListener);
mRequestQueue.add(gsonRequest);
}
We’ve created a CustomRequest named GsonRequest that serializes and converts the response into the POJO class internally. Also, the CustomRequest takes the headers as a constructor argument too.
Let’s see how the GsonRequest.java class is written.
GsonRequest.java
package com.journaldev.volley;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
public class GsonRequest extends Request {
private final Gson gson = new Gson();
private final Class myClass;
private final Map headers;
private final Map params;
private final Response.Listener listener;
public GsonRequest(String url, Class myClass, Map headers,
Response.Listener listener, Response.ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.myClass = myClass;
this.headers = headers;
this.params = null;
this.listener = listener;
}
public GsonRequest(int type, String url, Class myClass, Map headers,
Map params,
Response.Listener listener, Response.ErrorListener errorListener) {
super(type, url, errorListener);
this.myClass = myClass;
this.headers = headers;
this.params = params;
this.listener = listener;
}
@Override
public Map getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
@Override
protected Map getParams() throws AuthFailureError {
return params != null ? params : super.getParams();
}
@Override
protected void deliverResponse(T response) {
if(null != listener){
listener.onResponse(response);
}
}
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, myClass), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
A Custom Request requires the two methods, parseNetworkResponse
and deliverResponse
to be overridden.
The parseNetworkResponse parses the raw network response. In the above code, Gson library serializes it into a POJO class. The result is available in the deliverResponse
method.
In the deliverResponse
method, we’ve triggered a callback to the Response.Listener’s onResponse
method.
Hasn’t the above GsonRequest Custom Request simplified and generalized the code for storing a response in a POJO class.
The full source code for the MainActivity.java class is given below.
package com.journaldev.volley;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.LruCache;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btnGET, btnPOST, btnImageLoader, btnCustomRequest, btnImageRequest;
NetworkImageView networkImageView;
ImageView imageView;
ArrayList<UserList.UserDataList> mUserDataList = new ArrayList<>();
String BASE_URL = "https://reqres.in";
String IMAGE_URL = "https://www.android.com/static/2016/img/share/oreo-lg.jpg";
int numberOfRequestsCompleted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGET = findViewById(R.id.btnGET);
btnPOST = findViewById(R.id.btnPOST);
btnImageLoader = findViewById(R.id.btnImageLoader);
btnImageRequest = findViewById(R.id.btnImageRequest);
btnCustomRequest = findViewById(R.id.btnCustomRequest);
networkImageView = findViewById(R.id.networkImageView);
imageView = findViewById(R.id.imageView);
btnGET.setOnClickListener(this);
btnPOST.setOnClickListener(this);
btnImageLoader.setOnClickListener(this);
btnCustomRequest.setOnClickListener(this);
btnImageRequest.setOnClickListener(this);
networkImageView.setDefaultImageResId(R.mipmap.ic_launcher);
networkImageView.setErrorImageResId(R.drawable.ic_error);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnGET:
GETStringAndJSONRequest("2", "4");
break;
case R.id.btnPOST:
POSTStringAndJSONRequest();
break;
case R.id.btnImageLoader:
imageLoader();
break;
case R.id.btnImageRequest:
imageRequest();
break;
case R.id.btnCustomRequest:
customRequest();
break;
}
}
private void GETStringAndJSONRequest(String page_1, String page_2) {
mUserDataList.clear();
numberOfRequestsCompleted = 0;
VolleyLog.DEBUG = true;
RequestQueue queue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
String uri_page_one = String.format(BASE_URL + "/api/users?page=%1$s", page_1);
final String uri_page_two = String.format(BASE_URL + "/api/users?page=%1$s", page_2);
StringRequest stringRequest = new StringRequest(Request.Method.GET, uri_page_one, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response, "utf-8");
GsonBuilder builder = new GsonBuilder();
Gson mGson = builder.create();
UserList userList = mGson.fromJson(response, UserList.class);
mUserDataList.addAll(userList.userDataList);
++numberOfRequestsCompleted;
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.LOW;
}
};
queue.add(stringRequest);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(uri_page_two, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.wtf(response.toString(), "utf-8");
GsonBuilder builder = new GsonBuilder();
Gson mGson = builder.create();
UserList userList = mGson.fromJson(response.toString(), UserList.class);
mUserDataList.addAll(userList.userDataList);
++numberOfRequestsCompleted;
}
}, errorListener) {
@Override
public String getBodyContentType() {
return "application/json";
}
@Override
public Priority getPriority() {
return Priority.IMMEDIATE;
}
};
queue.add(jsonObjectRequest);
queue.addRequestFinishedListener(new RequestQueue.RequestFinishedListener<Object>() {
@Override
public void onRequestFinished(Request<Object> request) {
try {
if (request.getCacheEntry() != null) {
String cacheValue = new String(request.getCacheEntry().data, "UTF-8");
Log.d("API123", request.getCacheKey() + " " + cacheValue);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (numberOfRequestsCompleted == 2) {
numberOfRequestsCompleted = 0;
startActivity(new Intent(MainActivity.this, RecyclerViewActivity.class).putExtra("users", mUserDataList));
}
}
});
}
private void POSTStringAndJSONRequest() {
RequestQueue queue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
VolleyLog.DEBUG = true;
String uri = BASE_URL + "/api/users";
StringRequest stringRequest = new StringRequest(Request.Method.POST, uri, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response);
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.LOW;
}
@Override
public Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("name", "Anupam");
params.put("job", "Android Developer");
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
return headers;
}
};
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", "JournalDev.com");
jsonObject.put("job", "To teach you the best");
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(uri, jsonObject, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.wtf(response.toString());
Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public int getMethod() {
return Method.POST;
}
@Override
public Priority getPriority() {
return Priority.NORMAL;
}
};
StringRequest stringRequestPOSTJSON = new StringRequest(Request.Method.POST, uri, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
VolleyLog.wtf(response);
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}, errorListener) {
@Override
public Priority getPriority() {
return Priority.HIGH;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", "Android Tutorials");
jsonObject.put("job", "To implement Volley in an Android Application.");
} catch (JSONException e) {
e.printStackTrace();
}
String requestBody = jsonObject.toString();
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
};
queue.add(stringRequest);
queue.add(jsonObjectRequest);
queue.add(stringRequestPOSTJSON);
}
private void imageLoader() {
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
ImageLoader imageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> mCache = new LruCache<>(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
networkImageView.setImageUrl(IMAGE_URL, imageLoader);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(
networkImageView, R.mipmap.ic_launcher, R.drawable.ic_error));
}
private void imageRequest() {
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
ImageRequest imageRequest = new ImageRequest(IMAGE_URL, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
if (response != null) {
imageView.setImageBitmap(response);
}
}
}, 200, 200, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, errorListener);
mRequestQueue.add(imageRequest);
}
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (error instanceof NetworkError) {
Toast.makeText(getApplicationContext(), "No network available", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_LONG).show();
}
}
};
private void customRequest() {
mUserDataList.clear();
RequestQueue mRequestQueue = SingletonRequestQueue.getInstance(getApplicationContext()).getRequestQueue();
String url = String.format(BASE_URL + "/api/users?page=%1$s", "2");
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
GsonRequest<UserList> gsonRequest = new GsonRequest<>(url, UserList.class, headers, new Response.Listener<UserList>() {
@Override
public void onResponse(UserList response) {
mUserDataList.addAll(response.userDataList);
startActivity(new Intent(MainActivity.this, RecyclerViewActivity.class).putExtra("users", mUserDataList));
}
}, errorListener);
mRequestQueue.add(gsonRequest);
}
}
Android Volley Tutorial App in Action
The output of the android volley example application in action is given below.
Download Android Volley Tutorial Project
This brings an end to android volley tutorial. You can download the Android Volley Project from the link below.
{“imager”:[{“title”:”Guru”,”images”:[“images\/6.png”,”images\/androidIntro.png”,”images\/barretr_Earth.png”]}]}
this is my JSON array how to fetch images from this array
Hi i want to be android developer . what technology i have to learn . what is hybride app also work like native .
When to use native and hydride app development.