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);
}
Related
I need to make multiple calls to API REST with Retrofit and show the response in a ListView, but I don't know how to do this and this code doesn't work.
Model
#GET("apks/{sha256}")
Call<DatoAPI> getTask2(#Path("sha256") String hash, #Query("Authorization") String key);
Implementation
for (String s: hash) {
Call<DatoAPI> call = services.getTask2(s, API.API_KEY);
call.enqueue(new Callback<DatoAPI>() {
#Override
public void onResponse(Call<DatoAPI> call, Response<DatoAPI> response) {
if (response.isSuccessful()) {
datoAPI = response.body();
items.add(datoAPI.getApp());
}
}
#Override
public void onFailure(Call<DatoAPI> call, Throwable t) {
Toast.makeText(getApplicationContext(),t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
Also I tried with call.execute() and same problem
I want to show this response in a ListView but it doesn't work.
First of all you need to understand the differences between Retrofit's Call#enqueue() and Call#execute() methods.
enqueue() method is Asynchronous which means you can move on to another task before it finishes
execute() method is Synchronous which means, you wait for it to finish before moving on to another task.
And in your case, you're using for loop to execute multiple requests in a single stretch.
Now, if you use for loops to execute network operation, the network operation will not stop for loops from going to the next iteration. Do not expect that the API will always respond in a fast enough way before going to for loops next iteration. That's a bad idea.
If you use Retrofit's execute() method, it will not allow you to continue to next line (or iteration) as its Synchronous behavior, plus it throws NetworkOnMainThreadException and IOException. Hence, you need to wrap the request in an AsyncTask and handle IOException.
I'd recommend you to use RxAndroid with RxJava instead of using for loops. There are plenty of tutorials out there on this topic.
Refer to the following StackOverflow questions to solve your problem.
How to make multiple request and wait until data is come from all the requests in Retrofit 2.0 - Android?
Asynchronous vs synchronous execution, what does it really mean?
Adjust the code as per your requirements.
Good luck!
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
I am making an API call to a web service from the android application the problem is that it returns around 22000 records, I am loading this into an array after i convert each record into an object then assign that Array to a ListView. What is the fastest/best way to fetch this data from the web service? (buffer) ? and what are the best practices for this type of issues.
I would recommend using a library to handle your data call...
Please try using Android Query; specifically, see the section entitled Asynchronous Network.
This AQuery library (AndroidQuery) is lightweight, and requires only 1 jar SMALL jar file. It can be used with Maven or Gradle Android projects as well. It allows you to EASILY fetch XML or JSON data from a remote server in either asynchronous or synchronous fashion. I have used it many times with a JSON back-end, and it is a real timesaver.
This library also allows you to specify a ProgressBar that will automatically appear and disappear during the network download process.
Here is an example of an HTTP call to a JSON back-end, asynchronously:
public void asyncJson(){
//perform a Google search in just a few lines of code
String url = "http://www.google.com/uds/GnewsSearch?q=Obama&v=1.0";
aq.ajax(url, JSONObject.class, this, "jsonCallback");
}
public void jsonCallback(String url, JSONObject json, AjaxStatus status) {
if(json != null) {
//successful ajax call
} else {
//ajax error
}
}
AQuery can also simplify other aspects of Android programming (such as eliminating the findViewById() calls for many scenarios).
I have severals URLs I need to get data from, this should happen in order, one by one. The amount of data returned by requesting those URLs is relatively big. I need to be able to reschedule particular downloads which failed.
What is the best way to go? Shall I use IntentService, Loaders or something else?
Additional note: I would need not only to download, but also post process the data (create tables in db, fill it with data, etc). So DownloadManger can't be of help here.
I would use an IntentService.
It has a number of advantages that are suitable for your needs, including being able to download the data without your application running and supporting automatic restart of the service using setIntentRedelivery().
You can set a number of identifiers for the particular job, you need to perform using Intent extras, and you can keep track of the progress using SharedPreferences - that way you can also resume the work if it's been cancelled previously.
The easiest way is probably to use the system DownloadManager http://developer.android.com/reference/android/app/DownloadManager.html
(answering from my phone, so please excuse the lack of formatting)
I would suggest a service for this. Having service resolves many problems
It would allow reporting of progress asynchronously to the application so you can enable or disable a specific gui in application based on the download status of data
It will allow you to continue the download even if the user switches to other application or closes the application.
Will allow you to establish independent communication with server to prioritize downloads without user interaction.
Try a WakefulIntentService for creating a long-running job that uses wakelocks to keep your task alive and running https://github.com/commonsguy/cwac-wakeful .
Also, if your whole app process is getting killed, you may want to look into persisting the task queue to disk, using something like Tape, from Square
I think the way to go is loading urls in an array, then starting an AsyncTask, returning a boolean to onPostExecute indicating if the operation has success or not. then, keeping a global int index, you can run the AsyncTask with the next index if success, or the same index otherwise. Here is a pseudocode
private int index=0;
//this array must be loaded with urls
private ArrayList<String> urlsArray;
new MyDownloaderAsyncTask().execute(urlsArray.get(index));
class MyDownloaderAsyncTask extends AsyncTask<String,String,Boolean>{
#Override
doInBackground(String... input){
//downlaod my data is the function which download data and return a boolean
return downloadMyData();
}
#Override
onPostExecute(Boolean result){
if(result)
new MyDownloaderAsyncTask().execute(urlsArray.get(++index));
else
new MyDownloaderAsyncTask().execute(urlsArray.get(index));
}
}
hope this help
I have just completed an open source library that can do exactly what you need. Using droidQuery, you can do something like this:
$.ajax(new AjaxOptions().url("http://www.example.com")
.type("GET")
.dataType("JSON")
.context(this)
.success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
//since dataType is JSON, params[0] is a JSONObject
JSONObject obj = (JSONObject) params[0];
//TODO handle data
//TODO start the next ajax task
}
})
.error(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = params[0];
//TODO adjust error.options before retry:
$.ajax(error.request, error.options);
}
}));
You can specify other data types, which will return different object types, such as JSONObject, String, Document, etc.
Similar to #Murtuza Kabul I'd say use a service, but it's a little complicated than that. We have a similar situation related to constant internet access and updates, although ours places greater focus on keeping the service running. I'll try to highlight the main features without drowning you in too much detail (and code is owned by the company ;) )
android.permission.RECEIVE_BOOT_COMPLETED permission and a BroadcastReceiver listening for android.intent.action.BOOT_COMPLETED to poke the service awake.
Don't link the service to the Activity, you want it running all the time. eg we call context.startService(new Intent(context.getApplicationContext(), OurService.class))
The service class is just a simple class which registers and calls an OurServiceHandler (as in our case we fire off repeated checks and the Handler manages the 'ticks')
We have an OurServiceRunnable which is a singleton which is checked and called by the Handler for each test. It protects against overlapping updates. It delegates to an OurServiceWorker to do the actual lifting.
Sounds heavy handed, but you want to ensure that the service is always running, always ticking (via the Handler) but only running a single check at a time. You're also going to run into database issue if you use the standard SqlLite DbHelper paradigm, as you can't open the DB on multiple threads and you definitely want the internet access off the main thread. Our hack was a java.util.concurrent.locks.ReentrantLock protecting access to the DB, but you could probably keep DB access on the UI thread and pass DB operations via the Handler.
Beyond this it's just a matter of keeping the downloads atomic in terms of "get task, download task, complete task" or enabling it to pick up from a failed state eg downloaded OK, attempt to complete.
You should take a look at the volley library :
http://www.javacodegeeks.com/2013/06/android-volley-library-example.html
There is also an interesting video of the author that took place at google io 2013 :
http://www.youtube.com/watch?v=yhv8l9F44qo
Mainly because it eases the process of managing a lot of these fastidious tasks that are connection checking, connection interruption, queue management, retry, resume, etc.
Quoting from the javacodegeeks "Advantages of using Volley :
Volley automatically schedule all network requests. It means that Volley will be taking care of all the network requests your app executes for fetching response or image from web.
Volley provides transparent disk and memory caching.
Volley provides powerful cancellation request API. It means that you can cancel a single request or you can set blocks or scopes of requests to cancel.
Volley provides powerful customization abilities.
Volley provides Debugging and tracing tools"
Update from dennisdrew :
For large file, better use a variant of volley which authorize using another http client implementation. This link gives more details :
The volley article about this modification :
http://ogrelab.ikratko.com/android-volley-examples-samples-and-demos/
The github file detail :
https://github.com/ogrebgr/android_volley_examples/blob/master/src/com/github/volley_examples/toolbox/ExtHttpClientStack.java
public class FetchDataFromDBThread implements Runnable {
/*
* Defines the code to run for this task.
*/
#Override
public void run() {
// Moves the current Thread into the background
android.os.Process
.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
FetchDataFromDB();
}
}