Android Volley | Making A Synchronous Request


Photo Credit: jakedrzewiecki via Compfight cc

One of the newest frameworks in Android is Volley. This library was introduced to ease the process of making a REST web service call simpler. Usually the android volley library is used to make a request in background. For example, when a web service is called from an activity through volley library. A background worker thread is spawned, and in that thread web API call is made. After which the result is captured and returned back to the activity i.e the main UI thread. But in this tutorial I would show you how to make an Android volley synchronous request. That is, the calling thread would wait until the result is returned from the worker thread.

A point to note here is that, in any situation we should not do any sort of heavy work in the main thread. Also if you try to perform the below mentioned approach on the main thread of your app, you would get a TimeoutException. Therefore for making an android volley synchronous request I would spawn a thread and will make that thread wait until the response is captured.

Android Volley library is available through open AOSP repository. But as mentioned in this tutorial, there are two ways to include and use Volley.

Gradle Dependency

Include a gradle dependency in your project’s build.gradle (app) file:

compile 'com.android.volley:volley:1.0.0'

or

Library Project

Steps to include the Android Volley library in your project are:

  1. Clone the repo from this url:
    git clone https://android.googlesource.com/platform/frameworks/volley

    It can be done through any of the leading tools like Atlassian SourceTree, TortoiseGIT or through the GIT command line.

  2. In Android Studio goto File -> Import Module -> Specify the directory
  3. Enter the module name- “:Volley” (for internal project reference), hit finish.
  4. By now the gradle would start building the project. Let it complete.
  5. Open build.gradle file for your app module
  6. In dependencies block add a line compile project(':Volley')
  7. Go to Build menu -> Rebuild Project
  8. You are done importing Android Volley to you project.

Before starting with the code don’t forget to add an internet permission in your android manifest:

<uses-permission android:name="android.permission.INTERNET"/>

Custom Volley RequestQueue

To understand the basic working of volley, please have a look at my Android Volley tutorial. When using volley I prefer to use a single RequestQueue for my application, as it is easy to keep track of requests and responses throughout the app. Hence in this Android Volley | Making A Synchronous Request tutorial as-well I have customized the volley RequestQueue, by making it a singleton class. This way only one instance of volley RequestQueue would exist. Have a look at the code below:

package com.truiton.volleyblockingrequest;

import android.content.Context;

import com.android.volley.Cache;
import com.android.volley.Network;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.BasicNetwork;
import com.android.volley.toolbox.DiskBasedCache;
import com.android.volley.toolbox.HurlStack;

public class CustomVolleyRequestQueue {

    private static CustomVolleyRequestQueue mInstance;
    private static Context mCtx;
    private RequestQueue mRequestQueue;

    private CustomVolleyRequestQueue(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();
    }

    public static synchronized CustomVolleyRequestQueue getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new CustomVolleyRequestQueue(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            Cache cache = new DiskBasedCache(mCtx.getCacheDir(), 10 * 1024 * 1024);
            Network network = new BasicNetwork(new HurlStack());
            mRequestQueue = new RequestQueue(cache, network);
            // Don't forget to start the volley request queue
            mRequestQueue.start();
        }
        return mRequestQueue;
    }
}

Although to make an Android Volley synchronous request, it is not necessary to customize the RequestQueue. As I mentioned above its just a good way of doing it. In the above class if you see closely, you would notice that cache limit for the request queue has also been increased. In standard vanilla implementation of volley, the limit of DiskBasedCache is of 5 MB, for this example I have raised to 10 MB. This would allow us to cache a larger amount of requests. You can define it accordingly, as per your requirement.

Can I do a synchronous request with volley?

The answer is YES, though Android Volley we can perform a synchronous or blocking request. But first lets define a layout where all this action would happen.

<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:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".VolleyBlockingRequestActivity"
                android:background="#FFFFFF">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@drawable/truiton_short"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Request"
        android:id="@+id/button"
        android:layout_below="@+id/imageView"
        android:layout_alignLeft="@+id/imageView"
        android:layout_alignStart="@+id/imageView"
        android:layout_alignRight="@+id/imageView"
        android:layout_alignEnd="@+id/imageView" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:layout_below="@+id/button"
        android:layout_marginTop="26dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

</RelativeLayout>

To make an actual Android Volley blocking request lets define the activity:

package com.truiton.volleyblockingrequest;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.RequestFuture;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


public class VolleyBlockingRequestActivity extends AppCompatActivity {
    public static final String REQUEST_TAG = "VolleyBlockingRequestActivity";
    private TextView mTextView;
    private Button mButton;
    private RequestQueue mQueue;

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

        mTextView = (TextView) findViewById(R.id.textView);
        mButton = (Button) findViewById(R.id.button);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startParsingTask();
            }
        });
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mQueue != null) {
            mQueue.cancelAll(REQUEST_TAG);
        }
    }

    public void startParsingTask() {
        Thread threadA = new Thread() {
            public void run() {
                ThreadB threadB = new ThreadB(getApplicationContext());
                JSONObject jsonObject = null;
                try {
                    jsonObject = threadB.execute().get(10, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
                final JSONObject receivedJSONObject = jsonObject;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mTextView.setText("Response is: " + receivedJSONObject);
                        if (receivedJSONObject != null) {
                            try {
                                mTextView.setText(mTextView.getText() + "\n\n" +
                                        receivedJSONObject.getString("name"));
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }
        };
        threadA.start();
    }

    private class ThreadB extends AsyncTask<Void, Void, JSONObject> {
        private Context mContext;

        public ThreadB(Context ctx) {
            mContext = ctx;
        }

        @Override
        protected JSONObject doInBackground(Void... params) {
            final RequestFuture<JSONObject> futureRequest = RequestFuture.newFuture();
            mQueue = CustomVolleyRequestQueue.getInstance(mContext.getApplicationContext())
                    .getRequestQueue();
            String url = "http://api.openweathermap.org/data/2.5/weather?q=London,uk";
            final JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method
                    .GET, url,
                    new JSONObject(), futureRequest, futureRequest);
            jsonRequest.setTag(REQUEST_TAG);
            mQueue.add(jsonRequest);
            try {
                return futureRequest.get(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

In the above class I have started a standard java thread, on click of a button. This is the entry point of making a blocking request through volley. Since Android has a guideline that you can’t make network calls on main thread, it throws a network on main thread exception. I had to spawn a new thread, to make an environment where this synchronous type of request would actually come in use.

Please Note : In normal situations you should not be making this type of request.

After spawning a new thread called ThreadA, I started an AsyncTask (ThreadB) so that this can be put into waiting state, by calling get(long, TimeUnit) method of RequestFuture class. A volley class used for blocking requests. To access the get() method and make an Android Volley synchronous request, you need to use the RequestFuture class instead of standard StringRequest or JsonObjectRequest class. This RequestFuture class also implements both Response.Listener and Response.ErrorListener interfaces. Therefore it can be used as a listener as-well while making a request. The RequestFuture.get(long, TimeUnit) method returns the result immediately, as internally it calls the doGet(long) method, in a synchronized way. Hence instead of receiving the result back in onResponse(T response) method, we are actually waiting till the response is captured.

Android Volley Synchronous Request Diagram

Now since our AsyncTask (ThreadB) was also started in a blocking way by calling AsyncTask.get (long timeout, TimeUnit unit) method from ThreadA. Apparently ThreadA is also blocked at the moment. This is the key reason this cant be done on the main thread of your app. I tried doing it in the main thread and was not able to do it, as it used to throw a TimeoutException.

After completing the code, the screen should look something like the screenshot below:

Android Volley Synchronous Request

To understand the example better, please have a look at the full source code below:

Full Source Code

With this I would like to conclude my tutorial on how to make a blocking request with Android volley. If this tutorial helped you share it with your friends, also please like our Facebook, Google+ page.

About Mohit Gupt

An android enthusiast, and an iPhone user with a keen interest in development of innovative applications.


Leave a comment

Your email address will not be published. Required fields are marked *

2 thoughts on “Android Volley | Making A Synchronous Request

  • Mark

    Hi!
    There is a problem with the RequestFuture get() method. If a response is delivered, in the onResponse method the notifyAll() method is called. This will cause an InterruptedException in the doGet() method. So the response is delivered but it causes an InterruptedException by request.get(). The only way to solve it is to call request.get() again when an InterruptedException happens.