On Andriod, I'm trying to change the framework from AsyncHttpClient to Volley. There's a call back method onStart in AsyncHttpClient which helps me do something before I receive the response from the server. (Such as notifying the user to wait.)
I'd like to implement this functionality by Volley, but I didn't find a similar call back to implement. Can someone help me out? Thanks!
In Volley there are two types of callbacks:
/** Callback interface for delivering parsed responses. */
public interface Listener<T> {
/** Called when a response is received. */
public void onResponse(T response);
}
/** Callback interface for delivering error responses. */
public interface ErrorListener {
/**
* Callback method that an error has been occurred with the
* provided error code and optional user-readable message.
*/
public void onErrorResponse(VolleyError error);
}
There is no AsyncHttpClient onStart callback equivalent.
Example:
String url = "http://stackoverflow.com";
StringRequest request = new StringRequest(url, new Listener<String>() {
#Override
public void onResponse(String response) {
// handle response
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// handle error
}
});
RequestQueue requestQueue = Volley.newRequestQueue(context);
request.setTag(TAG); // you can add tag to request
requestQueue.add(request); // add request to queue
requestQueue.cancelAll(TAG); // you can cancel request using tag
Related
How to make Volley StringRequest should wait for the one response to complete and after completing the first response it should start another request.
you have to do if your first response successfully then call these second method your answers is into your question
Inside onResponse of your StringRquest make the second request you want.
StringRequest stringRequest = new StringRequest(Request.Method.POST, recieveMessageUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//create second request here
//and add it to queue
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Note: you will have to make sure that your response is valid otherwise the onErrorResponse will be called.
I'm using volley and I have a queue to call some APIs. The queue is filled from a database.
before adding request to volley request queue I set request tag by calling
jsonObjectRequest.setTag(id);
In response, I want to remove a column from the database that column id is equal to request tag id.
So, How can I get request tag in HttpRequest response?
First create a Listener that give response from your volly class
/** Callback interface for delivering parsed responses. */
public interface Listener {
/** Called when a response is received. */
public void onResponse(Object tag, JSONObject response);
public void onErrorResponse(Object tag, VolleyError error);
}
And now create method as below where you pass listener and tag and call volly request. in response you able get tag and response at same time.
public void callApi(String url, final Listener listener, final Object tag){
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
listener.onResponse(tag,response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.onErrorResponse(tag,error);
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
Its just sample code, You can modify on your requirement. If you need any help comment.
I have written an android library that does network calls to various websites and returns the necessary content. I am using Volley library which has callbacks like onResponse and onFailure. Initially this library was an app and was later changed to an library.
When it was an app I could handle the callbacks easily. Whenever the callback happens I call the required functions from there but now when I import as the library and try to use it the control returns from the library as soon as I call it and the call back is not doing anything.
public void sendForVerification(final String Response, final String Secret, final String Name) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
flag = true;
},
new Response.ErrorListener() {
#Override
public void onErrorResponse (VolleyError error){
flag = false;
}
}}) {
#Override
protected Map<String, String> getParams () throws AuthFailureError {
HashMap<String, String> params = new HashMap<>();
params.put("secret", Secret);
params.put("response", Response);
return params;
}
};
requestQueue.add(stringRequest);
}
}
When this code was a part of the app instead of returning the flag value I would call an appropriate function to handle the result. Now whenever I call these functions the value of flag is returned before the callback is done and this is causing some problem.
My question is how can I warp this around a callback so that the app that uses this library will be notified when the network call is done?
You could add your own callback(s) for your library
interface YourCallback<T> {
onResponse(T value);
}
public void sendForVerification(final String Response,final String Secret,final String Name, YourCallback<Boolean> callback){
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.onResponse(true);
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.onResponse(false);
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String,String> params = new HashMap<>();
params.put("secret",Secret);
params.put("response",Response);
return params;
}
};
requestQueue.add(stringRequest);
}
boolean flag;
api.sendForVerification("", "", "", new YourCallback<Boolean>() {
#Override
public void onResponse(Boolean value) {
flag = value;
}
});
Volley is asynchronus, so any other upcoming process after you send the request will continue as normal without waiting for a response. That's why your flag value seems like it hasn't changed, because you probably try to access it while the request is still waiting for a response. That's the reason of callback implementations: you take certain actions as soon as you get a response, and you shouldn't try to handle values that will be returned from another method, because they will be returned before they change.
I'm using google volley for networking in android. I will make a http GET request and need to return a response header value. I found some answers on stack overflow to access the header fields, but don't know how to return it to my calling spot.
Please have a look at my code, I put four numbers in it to explain my problem.
At (1) I can print out the value which I need. Than I've tried to save it in a class attribute (2) and there is no error in the IDE. If I want to return it from there (3), I got a NullPointerException at (4). Maybe its a read before write problem there.
So how can I get the value from (1) to (4)? Thanks a lot!
public class Login {
String phpsessid = null;
public Login() {}
public String getSessionId(Context context) {
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest sr = new StringRequest(Request.Method.GET, "any url",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
System.out.println(response.headers.get("Set-Cookie")); (1)
phpsessid = response.headers.get("Set-Cookie"); (2)
return super.parseNetworkResponse(response);
}
};
queue.add(sr);
return phpsessid; (3)
}
}
in main:
Login login = new Login();
String result = login.getSessionId(this.getContext);
System.out.println(result); (4)
When you add a request to the queue, that request is executed asynchronously. This means it is not executed in the same order as you're reading it - it happens on another thread, and will return eventually when it's done.
protected Response<String> parseNetworkResponse(NetworkResponse response) {
System.out.println(response.headers.get("Set-Cookie")); (1)
phpsessid = response.headers.get("Set-Cookie"); (2)
return super.parseNetworkResponse(response);
}
This returns the body of the response - from what I'm reading in your code, it looks like you want to return the value of the "Set-Cookie" header. You can do this like this:
protected Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
String sessionId = response.headers.get("Set-Cookie");
com.android.volley.Response<String> result = com.android.volley.Response.success(sessionId,
HttpHeaderParser.parseCacheHeaders(networkResponse));
return result;
}
This will return the value of the "Set-Cookie" header to your onResponse method:
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response);
}
}
A better idea may be to pass a success/failure listener in when making your getSessionId call. In this way, you can then easily get access to the result in the calling class:
public void getSessionId(Context context, final Response.Listener<String> successListener, Response.ErrorListener failureListener) {
RequestQueue queue = Volley.newRequestQueue(context); // This should be a singleton!
StringRequest sr = new StringRequest(Request.Method.GET, "any url",
successListener,
failureListener) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
String sessionId = response.headers.get("Set-Cookie");
com.android.volley.Response<String> result = com.android.volley.Response.success(sessionId,
HttpHeaderParser.parseCacheHeaders(networkResponse));
return result;
}
};
queue.add(sr);
}
Edit:
Now, you can call this as follows:
Login login = new Login();
login.getSessionId(this, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// You can access member variables from here.
// This will only get called after the network activity has happened!
phpsessid = response;
// All the work you need to do after your session ID has updated, you can put into a method and call it from here
// In your original example, this would be (4)
onSessionIdUpdated();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// We'll just ignore these for now - you should handle errors though!
}
});
// Anything you put here will happen immediately after the getSessionId call above, and notably *before* onResponse or onErrorResponse is called (ignoring potential race conditions here for now).
Here's my layout code;
static String userLocation(String url) {
RequestQueue queue = Volley.newRequestQueue(context);
// String url = "http://www.jobdiagnosis.com/iphone/userlocation.php";
StringRequest dr = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
res=response;
//edit_location.setText(response);
// Toast.makeText(context, response, Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error.
Toast.makeText(getApplicationContext(), "error"+error, Toast.LENGTH_LONG).show();
Log.d("error", ""+error);
}
}
);
queue.add(dr);
return res;
}
When I toast the response on same method then response prints fine
and when I call method and print return statement then res prints null.
Any help is appreciated. Thank you in advance.
Please suggest me how we can share response within a one or more activity
And sorry for my bad English..
this is an asynchronous request, the volley processes the request in background thread and delivers the response in onResponse()
if you're looking for synchronous response try this
Try to declare res like global variable. Not return value. Because you didn't know, when request will finished. And use this global variable.