I'm using Volley for all my network related code. Since Volley does the actual networking part off the main UI thread I havent really thought much about it but I realize now that in a few instances I do some significant processing of the response data in onResponse(). It seems like this code does indeed run on the main thread. What's the best way to do this? Should I define a AsyncTask for that specific portion of the code or should I just put the entire network request in a AsyncTask despite Volley's threading mechanisms.
I would suggest NOT to use AsyncTask as it has its own drawbacks in case activity is destroyed or recreated. And moreover if you are using Volley's queueing mechanism, this will just work as a add-on.
One solution I can think of is to use Loaders. Make the network call and process the response in loadInBackground method. And when onLoadFinished is called, you'll get the processed response.
Another solution (Not recommended and not so efficient) is to use a Service. You can make the network call from the Service and process the data and communicate back to the Activity.
Related
I want to control a RaspberryPi via android app and plan to do this by defining an api on the raspberry and accessing it via the app.
On the Android Developer Guides I found the recommendation to implement a DownloadCallback interface.
My question is, why would I want to do that, if I can alternatively simply use an AsyncTask and make an HttpRequest?
Using an AsyncTask for network calls is considered a bad idea. First, AsyncTask does not handle orientation correctly so you need to have more code put in so that the asynctask properly terminates (making sure it doesn't make calls to the finishing activity, making sure it doesn't hold any strong references to the finishing activity). You also cannot halt AsyncTask so lets say in your main UI thread, you want to stop the AsyncTask from performing the network call but you already started it. Well you are out of luck and you need to wait until it terminates on its own. (As mentioned in the comment below, this is not true. You can halt interrupt the thread of the AsyncTask to "cancel") Also, you cannot make parallel network requests in an AsyncTask easily.
Also this is more of a preference but using AsyncTask is more boilerplate code than I would like. Retrofit is my most preferred way of network operations.
DownloadCallback isn't about replacing the AsyncTask. It is just a way to communicate between your fragment (the one who started the network call) and the activity (the one who wants to know what the progress of the network call is) about the progress of your network operations. You can see here https://developer.android.com/training/basics/network-ops/connecting that they are still using AsyncTask for network operations but they are using the DownloadCallback to notify the activity about the progress of your operation.
Our app needs to hit some REST services for data (less than 500KB mostly). I was analyzing what should be the best approach for handling the api calls. Possible options were:
AsyncTask (seemingly the right candidate as per the Google docs.)
Thread (regular java threads)
All we have inside an AsyncTask is the doInBackground() method that does the network call and the onPostExecute() that posts the result to a handler class (a java class; not android.os.Handler). The handler posts the result via EventBus to the calling Activity/Fragment.
The only advantage over a traditional Thread that I see by using the AsyncTask here is that the result is posted on the UI Thread. I read that AsyncTask pose the risk of a potential memory leak if the activity is destroyed as described in many threads in SO.
To avoid this, we are thinking of spawning regular Threads for the network access and use EventBus library to post the result directly to the UI thread in the Activity/Fragment. This gets rid of the Handler class to post the result and also the code looks cleaner.
My questions are:
Is AsyncTask still the recommended approach inspite of the extra lines of code and the handler classes?
Does the use of a regular Thread instead of an AsyncTask come with some risks that we have missed? We are only starting the Thread but not handling its lifecycle.
Is the use of EventBus for our purposes correct?
Thanks in advance for your help.
OKHttp supports both synchronous and asynchronous api.
If I want to issue an async request, I can:
Use a AsyncTask, and issue OKhttp synchronous api.
Issue a OKhttp asynchronous api.
What is the difference between these 2 options? And which one is better?
Quite a lot differs!
Using AsyncTask for HTTP requests is pretty much one of the worst things you can do on Android. It's fraught with problems and gotchas that are best unconditionally avoided. For example, you cannot cancel a request during execution. The patterns of using AsyncTask also commonly leak a reference to an Activity, a cardinal sin of Android development.
OkHttp's async is vastly superior for many reasons:
It supports native canceling. If a request is in-flight, the reference to the Callback is freed and will never be called. Additionally, if the request has not started yet it never will be executed. If you are using HTTP/2 or SPDY we can actually cancel mid-request saving bandwidth and power.
It supports tagging multiple requests and canceling them all with a single method call. This means every request you make in, say, an Activity can be tagged with the Activity instance. Then in onPause or onStop you can cancel all requests tagged with the Activity instance.
If you are using HTTP/2 or SPDY requests and responses are multiplexed over a single connection to the remote server and by using the asynchronous Call mechanism this is much more efficient than the blocking version.
So if you can, use Call.enqueue!
Nothing much. OKHttp async is OKHttp API driven. So as long as you bundle the jars together for all platforms you should be good. AsyncTask is Android way of doing things.
However since Honeycomb Async task runs the tasks sequentially and not in parallel. This means that though the execute method of AsyncTask spans a new thread which runs your job away from the UI thread but all the tasks sent to one AsyncTask run in the same spanned thread.
So for 3 tasks submitted u don't get 3 threads they all run sequentially on a single spanned thread. With OKHttp you can achieve true parallelism using callbacks and async GET and POST.
Though you can do true parallelism in AsyncTask methods as well (check the overloaded execute methods in AsyncTask) but default Android behavior is not to do so.
I kinda liked Volley framework, but I still have some doubts about it.
For example, how does Volley line up with Loader pattern? Since it's requests are handled in an async manner, calling it on background doesn't make much sense. On the other hand, if we ignore the Loader pattern, we will cancel the loading and reload the necessary resources, it's kinda waste.
How does Volley framework work with Loaders in Android?
A Loader can encapsulate practically anything, including Volley requests. When your Loader encapsulates a framework that already handles background work for you and calls you back on the main thread, like Volley, your loader implementation must not inherit from AsyncTaskLoader but simply from the Loader base class. You would then start the Volley request in the onForceLoad() method.
When your loader gets the result back on the main thread through a callback, it just needs to push it to the Activity/Fragment by calling deliverResult().
Your loader would also need to keep a reference to the Volley request in progress to be able to cancel it in onStopLoading(). onStopLoading() is not called in case of configuration change like screen rotation, only when leaving the Activity.
The only disadvantage is that Loaders don't have a built-in mechanism to propagate errors, while Volley does. So in your Volley error callback inside of your Loader, you'll need to either deliver a null result or send a local broadcast to notify the Activity/Fragment of the error.
AFAIK and I have seen in the sources, responses to your requests will be cached, IF the server sends the proper caching headers(ETag), and the second time you will attempt to make a GET request, to the same url, you will be provided with a response from the cache, instead of calling the Network again.(by default Volley caches the requests using as key the URL).
Adding Requests to the RequestQueue should be done from the MainThread, as it makes no sense to call them from a background Thread.
I just publish an article about Volley and it integration into project over Loader pattern. Advanced approach is shown. Loader states are fully defined and displayed in diagram.
Article: https://plus.google.com/117981280628062796190/posts/8b9RmQvxudb
It is possible to make synchronous requests with Volley via the RequestFuture class. I haven't looked into this personally, but it looks like you could leverage that with a Loader to get the best of both worlds (Volley's Cache with the loading stability of the Loader).
Here's scenario:
Client makes remote call to the service (returns void) and provides
a callback object
Service executes some long running logic on the background thread
and then uses callback object to trigger ether success or failure
which (since these manipulate visual elements) execute in
Activity#runOnUiThread block
The scenario runs fine. The question is - can I use AsyncTask to make
code less verbose (how?) and would be there any advantages in doing it
that way?
Or should I just get away from client callbacks alltogether and
execute remote service calls retrofitted to return some value within
AsyncTask#doInBackground?
It is difficult to say whether AsyncTask will make things less verbose, since we don't know the verbosity of your current implementation.
For me, AsyncTask means I don't have to worry about cleaning up threads myself (e.g., post some sort of kill job to a LinkedBlockingQueue my background thread is waiting on). It also eliminates the custom Job classes I used to create for using with LinkedBlockingQueues. And, it simplifies a bit doing final work back on the UI thread.
In your case, with a remote service, the UI thread issue is less critical, since the activity needs to handle that itself.
I don't see what the difference is between your #2 and your last paragraph. In both cases, your service will call the callback object, which will use something like runOnUiThread() to arrange for the work to be done on the UI thread.
AFAIK, the only two ways to have a service doing any sort of asynchronous work let the client know that work is done is by a broadcast Intent or a callback object. Broadcast Intents are convenient but public (i.e., other code can watch for them).
I suspect I probably have not helped much here, but I just don't know enough of your scenario to provide greater detail.
I'm having quite the same question : i'm developping a map activity, with a 'lazy-loading' functionnality (xml from Network, parsing it, then updating my map with the 'items' created from that parsing...)
i wondered what would be 'the best' way to implement it...
async service launched from a thread, an update notification via Intent?
just a thread (no service, since i don't need to expose it to other applications) w/ callback
asyncTask with callback
i'm comparingthese in terms of speed, using the Android SDK performance analysis Tool traceview
I guess a more precise answer might be found from Android contributors on the Android-developper-group...