Reputation: 1478
Consider this code in an Android activity, using the Volley HTTP library. The HTTP request never completes. It neither receives a normal response nor an error response. But if the while (!done)
block is commented out, then everything completes normally. This surprises me since with Volley I'm making a RequestQueue
which contains a thread pool where entirely separate threads are used to carry out the HTTP request. So why does the request never finish if this thread is sleeping?
The code:
package com.adobe.instore.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.adobe.instore.R;
import com.adobe.instore.Urls;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONObject;
public class VolleyTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_volley_test);
}
private static boolean done = false;
protected void makeRequest(View v) {
Log.i(getLocalClassName(), "Request");
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
queue.start();
queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(getLocalClassName(), "Response");
done = true;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(getLocalClassName(), "Error");
}
}));
Log.i(getLocalClassName(), "Awaiting completion");
while(!done) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(getLocalClassName(), "Done");
}
}
Upvotes: 0
Views: 1014
Reputation: 7415
Views are rendered in the Main Thread (sometimes called UI Thread). The loop you made blocks the rendering and the other code that follows. Technically it is a bad idea to call Thread.sleep(...);
in this thread since many things will be affected. Volley is a http library designed to make your life simpler by not needing to explicitly call a Thread of your own.
In Volley all the networking and cache dispatching are done in a Separate thread (behind the hood) while the response is sent back to the Main thread. That just means that onResponse
and onError
happens in the Main thread.
To make it more simpler you can do like this:
public class VolleyTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_volley_test);
}
public void makeRequest(View v) {
Log.i(getLocalClassName(), "Request");
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
queue.start();
queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(getLocalClassName(), "Response");
Log.i(getLocalClassName(), "Done");
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(getLocalClassName(), "Error");
}
}));
Log.i(getLocalClassName(), "Awaiting completion");
}
}
Furthermore the while()
and Thread.sleep
keeps the Thread busy. So any executions queued in the Main thread are unreachable till the loop is done (but it wont happen). You might be thinking that the onResponse
can bypass that infinite loop? The answer is NO; because onResponse
is queued by the Main thread and not the background Thread. To illustrate see figure below:
Figure 1 : Android Volley internal architecture (image is from the docs)
If you look that box that says Parsed response delivered on main thread which is colored as BLUE meaning it is the Main thread who call it (to simplify it means onResponse
and onError
are called by the Main thread) unless it is orange or green then loop will be bypassed by your boolean.
Upvotes: 1
Reputation: 3652
Volley onResponse and onErrorResponse is called on UI thread. So if your main thread is sleeping, then onResponse and onErrorResponse will not be called
Upvotes: 1