I have a for loop , which is creating different url and then i am pushing the urls in the Volley RequestQueue using add function.
I have a question that , will the response listner will be responding in the order of the request added to the RequestQueue or it will be random based on the server responses of the requests made?
I am using VolleySingleton approach.
Volley RequestQueue class manage asynchonous requests queue.
It means Volley send requests on a FIFO (first in first out) model, but since responses can be quite long to come back, it handle responses in no particular order.
You can't use it if you want the result of a first request to be used in a second request.
However, you can visibly use RequestFuture class to use Volley on a synchonous model:
Can I do a synchronous request with volley?
By default, Volley RequestQueue will use 4 concurrent Threads to process the Requests added to the Queue. This may be changed by extending the RequestQueue class and passing the desired Thread pool size as the third parameter to super contructor.
Passing 1 to the constructor will result in the RequestQueue processing one Request at a time :-)
Reference
No! Android volley process each requests in request queue Asynchronously:
Refer the architecture image:
Each requests in the request queue will be processed by the network threads and also you can limit the network dispatcher thread count check here
Assuming that the default behavior is to send multiple requests on separate concurrent threads, then the order of the responses then becomes dependent on the total response time for each individual request.
As to identifying the responses (other than the data itself), it seems like you should be able to instantiate a Response.Listener implementation with a unique request identifier (original URL or int) such that when the response handler is invoked it is able to differentiate the original request.
public class JSONProcessor implements Response.Listener<JSONObject> {
private String url;
private int reqCode;
public JSONProcessor (String reqUrl) {
this.url = reqUrl
}
public JSONProcessor (int reqCode) {
this.reqCode = reqCode;
}
public void onResponse(JSONObject response) {
// use this.url or this.reqCode to determine original request
// process response
}
}
Alternatively, use different implementations of Response.Listener for each endpoint you expect to be processing.
In general, in my opinion it is best to be completely data driven if at all possible.
Related
I'm confused about post and get request in android volley.
Can you explain me their differences?
And can I use post method with no Param to get a JSON from URL?
Their difference is in functions defined in server.
In simple words, With a GET method, you are sending your data via the URL. While, with A POST method, data is embedded in the form object and sent directly from your browser to the server. ... We usually use GET to identify and dynamically render pages and POST to send form data but it's not always the case.
and answer of your second question is yes you can but that's not a good idea get would be better for that. here is a example of how you can send requests using Volley Library
StringRequest request = new StringRequest(Request.Method.POST, "www.example.com", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> parameters = new HashMap<>();
return parameters;
}
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}
};
AppController.getInstance().addToRequestQueue(request, tag);
Are you working on server or server is handled by someone else?
In general, person who works on server decides the method.
Like if you work on JAVA server, then say an API end point is https://sample.api.someurl.com/userInfo/
TO maintain some consistency server programmer may use GET method to get userInfo and he may use POST method to update user info and he may use DELETE method to delete the existing user info.
In this example, your API end point remains same but the request method decides how that end point will behave.
In other example, to save time, a server developer may redirect all the requests to one method and handle it there, so no matter you call GET, POST or DELETE API will return same response.
So yes, Its not Android or UI developer who decides the Method alone, Major role of deciding which method to use is decided by server programmer.
P.S. If you are working on server too, then good practice is to use GET to get the info, POST method to update or add the info and DELETE to remove the info.
I've been trying to implement an interceptor ( OkHttp 3.2 & Retrofit 2 ) for editing the JSON response before is returned as response. The server we request data returns different data dependes on success or error and that makes difficult to map the objects.
I was trying to do it by adding the interceptor to Retrofit as a NetworkInterceptor, however the string returned had no format.
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
try {
final String responseString = new String(response.body().bytes() );
LOGD("OkHttp-NET-Interceptor", "Response: " + responseString);
String newResponseString = editResponse( responseString );
LOGD("OkHttp-NET-Interceptor", "Response edited: " + newResponseString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), newResponseString))
.build();
}catch (Exception ex){
return response;
}
}
responseString had a string without any understandable format.
After changing to the normal interceptor, the string had format a it was able to convert to JSONObject.
Could tell me someone which are the differences between the responses?
why this line new String(response.body().bytes() ); return different content?
The differences are in the names. NetworkInterceptor hooks in at the network level and is an ideal place to put retry logic and anything that doesn't rely on the actual content of the response.
If what you do depends on the contents of the response (like in your case), using a ApplicationInterceptor is more useful, as it gives you the response after it's been processed by any other moving parts you may have such as a JSON deserializer. Otherwise you would have to implement the JSON deserializing yourself inside the NetworkInterceptor which doesn't make much sense considering it's done for you by Retrofit.
Clarification
Square have this useful diagram on their wiki that shows where each type of interceptor sits
Thus, the reason you receive a readable string in the ApplicationInterceptor is because Square are trying to de-couple the purposes of the two interceptor types. They don't think you should be making any application dependent decisions in the NetworkInterceptor, and so they don't provide an easy way for you to access the response string. It is possible to get ahold of, but like I said, they don't want you to make decisions that depend on the content of the response - rather, they want you to make decisions based or the network state, or headers etc.
The ApplicationInterceptor is where they want you to make decisions dependent upon the contents of the response, so they provide easier methods to access the content of the response so that you can make informed decisions to retry, or as they detail in their wiki, rewrite responses (which I believe is what you're trying to do).
According to #square:
Each interceptor chain has relative merits.
Application interceptors
Don’t need to worry about intermediate responses like redirects and retries.
Are always invoked once, even if the HTTP response is served from the cache.
Observe the application’s original intent. Unconcerned with OkHttp-injected headers like If-None-Match.
Permitted to short-circuit and not call Chain.proceed().
Permitted to retry and make multiple calls to Chain.proceed().
Can adjust Call timeouts using withConnectTimeout, withReadTimeout, withWriteTimeout.
Network Interceptors
Able to operate on intermediate responses like redirects and retries.
Not invoked for cached responses that short-circuit the network.
Observe the data just as it will be transmitted over the network.
Access to the Connection that carries the request.
I'm using volley to get a JsonObject from a URL. My problem is that often I get an OutOfMemory Exception. I used to MAT to analyze the memory leaks and I see that the whole object on response after downloaded and used it is still on memory. What I'm doing wrong?
Volley Code
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
item = parser.parse(response);
updateLayout();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
bar.setVisibility(View.GONE);
if(!isNetworkAvailable()){
Toast.makeText(act, "No Internet Connection.", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(act, "The Server Is Down. Try Again.", Toast.LENGTH_SHORT).show();
}
}
});
// Adding request to request queue
VolleySingleton.getInstance().addToRequestQueue(jsonObjReq);
MAT screenshot
Ok i think your problem is here:
Network dispatcher is a thread that his duty is to send the request to the server and getting results, he manages the http connection and he is your outside interface, so each objects in this thread is those who their request are in the flight and have been sent to the server and are waiting to get back the result , these are other requests no the one that you get the result in on response. Network response is the one that manages parsing the response and delivers it to you after response delivered to network dispatcher. i suggest you to look at the source code to better understand this beautiful framework. i think your problem is coused by parser or your long json so you can eliminate it by providing bigger cache for volley or another joson parser technique.
Update:
i mean that those hashmaps are not memory leak, those are your other requests to the server, you have not specify any memory leak in your image. what you have shown on the picture is your other requests that you sent to volley. when you send your request to this library, this library creates multiple request connections to the server to make your network operation be speedy. those multiple requests take time to go from your device to the server and come back with response. those request and connection are all managed by network dispatcher. it makes multiple connections and sends requests to the server. so what you see on the image is those requests that have not gotten results yet from server. so those 3 items must be into the memory because those are requests that you want the results for them.
after you exit from response block {} imean last brace your response automatically removed from memory, so do not worry about your response. i think your problem dose not relate to volley buges or any thing else about this library. i think you must check other aspect of your apps like the method of parsing json or ...
After finising my app leak search, I finally understand why volley keeps request in memory . In my case, I use volley singleton mode. Volley has 4 threads do network dispatch, and each thread keeps a request.
when you do more than 4 times request, there will always be 4 requests keep in memory. without other leak problem ,request would not raise .
Usually, we use new Anonymous Inner Class request , which will keep a strong reference to outer class . so we will see Activity not GC after onDestory().
As a result, Volley not have big problem, if you do not want request Keep strong reference to your class ,so use weakReference.
Your OOM problem must be something else caused.
I read a post about Volley and I know it's great networking library. But I couldn't understand one thing.
All requests are Async Task or not?
When I want to send asyncTask request using Volley do I need put Volley request in AsyncTask?
or should I just call Volley Request if it is already AsyncTask request?
private class MyClass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// do Volley request
}
}
Is this right approach?
You don't need to run Volley request on AsyncTask.
Why:
They manage all network related task on separate thread.
If you look closely at library project they did not picture the AsyncTask.
But they intelligently handle all network related task efficiently.
Check RequestQueue.java class in Volley's main package
here I am pasting java doc.
/**
* A request dispatch queue with a thread pool of dispatchers.
*
* Calling {#link #add(Request)} will enqueue the given Request for dispatch,
* resolving from either cache or network on a worker thread, and then delivering
* a parsed response on the main thread.
*/
Edited:
Forming a Request:
With Volley, network communication is managed by the RequestQueue. The best way to utilize the RequestQueue and all of its tools, especially the cache, is by instantiating it once and keeping it around as a singleton. At this point you can then add or cancel requests, stop or start requests, and access the response cache(s).
RequestQueue queue =Volley.newRequestQueue(this);
Once the RequestQueue has been instantiated a request must be formed. This can be done utilizing a few different “out of the box” request classes included with the Volley Library or by extending Volley’s request class into your own custom request. The request classes already included in Volley are a String request, JSON requests, and an Image Request. Most of the request classes included in Volley library utilize constructors much like the one below.
Parameters being passed into constructor:
RequestMethod(get, post, delete, ect)
JSONObject-An optional object that will be posted with your request
ResponseListener- Where your data will go after the request is complete
ErrorListener – What will be told when there was a problem with your request.
JsonObjectRequest request = JsonObjectRequest(Requestmethod, url, null, new ResponseListener(), new ErrorListener());
Listners to receive response:
Successful Response Listener
private class ResponseListener implements Response.Listener{
#Override
public void onResponse(JSONObject response){
}
}
Error Response Listener
private class ErrorListener implements Response.ErrorListener{
#Override
public void onErrorResponse(VolleyError error){
}
}
Finally add your request to Request queue, rest of everything Volley will handle for you.
Making call:
Now, that we have made our request and response classes we are ready to add the request to the queue and retrieve the data. To do so we simply add the request to the queue.
queue.add(request);
The response or error will then be delivered to the response/error classes that we defined in our request. You can add as many requests to the queue that you would like at one time and the responses will be delivered to their respective response/error classes
When you use Volley, there's no need to combine it with AsyncTask. It does the networking stuff on another thread for you.
Here is a basic example of a network call using Volley. As you can see, all the code is just in the Activity, without any need to define an AsyncTask.
Volley cannot be inserted inside AsyncTask because,
Volley is initiating background thread(s) on its own so all the network requests are executed off the UI thread so primarily you don't need to extend AsyncTask anymore. Of course you will have to take care to cancel the running requests on rotation or when user exits your activity..
As Volley is mainly used for minor Networking purposes in Android (for major use DownloadManager). It does similar working of AsyncTask Class. Implement Singleton in Volley.
Images can also be sent in Volley.
The whole point of introducing Volley library was to make sure user doesnt have to worry about all the "obvious" stuff while sending a network request. This means that volley takes care of the following on its own
Switching Background thread
Transparent disk and memory response
Multiple concurrent network connections. etc
To answer your question- You don't need to worry about switching to background thread, Volley takes care of this on its own. Also once the request is completed the success or failure callback is invoked on the main thread.Hence with Volley developer need not worry about switching threads
This tutorial here gives a good step by step explanation of Working with Volley Library
It is easy to maintain progress bar state when i use AysncTask with fragments Callback but how should i achieve it with volley? I can;t use AsyncTask because it is outdated and volley is better and faster.
Any Help or Hint will be grateful.
I am using google's volley to Post and Get Requests
I think there are misconceptions here.
First off, Volley faster than AsyncTask.
This is comparing apples and oranges. They both use threads. Volley threads are not any faster than the threads in async task. The queues are separate but that is about it. In API 11 & higher you are allowed to use your own threadpool for AsyncTask instances.
Second, define better.
Volley is designed for sending a lot of light payloads (GET/POST) to a server and getting back pretty quick responses. These responses can then be used by the caller.
AsyncTask is designed to complete a given task off the UI thread and provide various callbacks as to the state of that task.
For your ProgressBar I am assuming you are trying to determine the progress of a request that is being executed. In the Volley world, since these are expected to be tiny, you have pretty much 3 states.
Not Started
Executing(also contains start parsing)
Done (comprised of success, error and cancelled and such)
As you know with AsyncTask there is a callback for onProgress when using publishProgress. So your instance can define anything it wants to send through as an indication of progress.
If your payload is big and will take time to transfer to the server, Volley may not be appropriate. Volley doesn't do a great job or even try to do a great job of sending large payloads to and from a server. The reason is that this just isn't what it is meant for. Like it requires that all payloads, upload and receive can fit in memory entirely. So If you have a few volley requests going all over, and each one with like a 1MB payload and a 1MB response, you could see this adding up pretty quickly. You would need a streaming option to better handle that.
Volley is great library but consider what it is recommended to be used for. Read the documentation and implementation of the code for more info.
If you are doing something that is going to take a rather long time, I would write a specific request type in volley that sends and streams content to and from. That way you can tell how much work is left with the request. I am assuming you are using bytes sent and receive as the measure for progress.
you can add a listener to the queue which is executed when the request end
mRequestQueue.add(yourRequest);
mRequestQueue.addRequestFinishedListener(new RequestQueue.RequestFinishedListener<String>() {
#Override
public void onRequestFinished(Request<String> request) {
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
}
});
It's a pretty simple fix. Before you make your volley request, call the method progress.show(), and then on your response, call progress.dismiss() Just did this and it works great!
It's very easy to do that.. see the below code snippet
sendJsonRequest(){
///ENABLE PROGRESS BAR HERE
enableProgressBar();
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
hideProgressDialog();
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressDialog();
}
});
queue.add(jsObjRequest);
}