Multithreaded HTTP Request Queue System Approach - android

I've read alot of different recommendations on how to use locks - but the behavior of my current code in both IOS and Android does not behave correctly.
What I'm trying to do is build a queue system with a HTTP Request. If a Request fails, it should be the first request to be retried. Both send and add to queue is in the same method, so it shall not add a new object into the queue until the previous request has finished. If one fails and when the next request gets added it would send two requests (in the same package and clearing the queue).
Android:
// Java
synchronized(locker)
{
Add object to a queue if there is a new object to be added
If any objects in queue - send request with AsyncTask
}
IOS:
// Objective-C
#synchronized(locker)
{
Add object to a queue if there is a new object to be added
If any objects in queue - send request with NSURLSessionDataTask
}
...and on fail, do not remove the object from the queue.
In this case - I am guessing that the lock does get released and another thread could possibly be sending the next request right away and come first since the tasks are dispatched in another thread?
I've tried with normal locks with some success on Android and complete failure on iOS where the entire system freezed up. Since then I've read about locking a lock on IOS that it has to be unlocked by the same thread - would a dispatch_async(dispatch_get_main_queue()... on the entire method work or would I have to dispatched it again when the completitionHandler finishes? Can I be certain that the completitionHandler is called on the same thread as the method creating it?
It's very important that each package are sent in the correct order. What is the best approach towards a multithreaded HTTP Request system like this?

Don't spawn new threads by AsyncTask or NSURLSessionDataTask. If you need the threads to serialize, i.e. at most one of them may run at the same time, and the next one has to wait for the first one to finish completely, there's absolutely no reason to run multiple threads.
You're going to want one (1) thread for all requests, and maybe send data to it using a queue. Otherwise, the UI might freeze while sending http requests.

Related

Waiting for a server task to complete

I have a situation where I have to do a server call from Android and based on the result of the call ( result would be either true or false) I want to proceed ahead in the code flow and pop a Dialog based on this result. Till the call is complete I don’t wish to proceed ahead in the code flow or logic. In short, I want to carry out a sync operation
At the server side, I will receive a HTTP Post request from android client and based on the parameters in the POST I do some processing by fetching values from the DB and return back true or false to android client.
To carry this out correctly on Android side, I researched and got two options.
Using Handler with AsyncTask does not work in my case because if
I use AsyncTask with Handler, the task result will arrive
sometime in future in Handler and the calling function will return
immediately whereas I want the calling function invoking
AsyncTask to finish i.e. wait till the server returns backs before I
proceed ahead .
The other option that I came across was to use
AsyncTask get() method . Since I am not carrying out a long running
task and rather performing a simple calculation on serverside, this
may not cause a an ANR situation even if I block the UI thread.
Are there any better options of carrying this out ? Is AsyncTask get() here actually one of the correct uses of get() ?

Background HTTP Request/processing that allows aborting

I need to make a http request in my main activity and if the request completes while the user is reading the basic info in this activity, I must store the returned info in a variable. However, if the user clicks in a button in this activity, another activity will be opened. This new activity will continue waiting the same request started from main activity, and display the data when it finishes.
I've read about IntentService, however it can't be aborted (am I right?) and the user can ask for new data before the request is completed.
What alternatives do I have?
PS: The request will only work while the app is running.
PS2: I'm using Volley for http requests.
Sounds like you might want to use a Service instead of an IntnetService, since volley will kick off on a separate thread. You can then handle the management of the volley task in that service.

Does Volley library handles all the request sequentially

I am using volley library for performing network operation to speed up the things. My Question is that Does Volley executes the requests which have added in the queue sequentially or parallel.
Suppose I add request like Req1, Req2, Req3 , Will they start to run parallel or second request will wait until first finished ??
According to the Volley documentation
Volley maintains several network threads. If a thread is not doing anything, then it will take on a job in the queue.
To answer your question, Req1, Req2 and Req3 will each be placed in a worker thread and will run in parallel.
Volley also caches your downloaded data (and determines whether to re-download based on the expire time in the HTTP header of the downloaded data), so if your data doesn't need to be downloaded again, it's fetched from the cache, which is faster than re-downloading.
These are some of the reasons that Volley is proclaimed to be faster than standard network operations for the situations that it's appropriate to use it. You can, of course, implement this yourself, but Google has done a lot of the hard work for you.
Usually a queue starts each operation according to the order it was queued, unless it's a priority queue.
Therefore, assuming equal priority (Assuming that the Volley queue is non priority queue), we can conclude that Req1 will get started first. Then Req2, followed by Req3.
However, we can not guarantee the order which each finishes. If Req1 is time consuming, then the requests will finish in a different order than Req1, Req2, Req3.
All we can guarantee is that they will be started in the order Req1, Req2, Req3.

How do you remove "bad" Tasks from a Tape ObjectQueue?

I'm using Square's Tape library to persist HTTP Request Tasks to disk so that if I make a request and it fails due to things like network errors or server issues, the request won't be lost and can be tried again later.
Is there a recommended strategy for removing "bad" tasks from the ObjectQueue? I can imagine a possible scenario where you create a malformed HTTP request task, add it to the task queue, and then try to process it in a service like in the tape-sample code. Because the request is malformed (or maybe the service its trying to hit has been retired), the request never succeeds and the request just kinda sits in the queue forever blocking further added requests from ever being processed. I suppose one option could be to keep track of the number of failed attempts for the head task.

Android Asynk Task

is a good practice to have an Asynk task with a loop like this inside?
while (true) {
check queue and request API
Because i need to wait for my Activities and service needs to comunicate with the APi.
Thanks
I am assuming the "queue" is a Java queue, perhaps a LinkedBlockingQueue. If so, that queue is unnecessary, as AsyncTask has a queue to go along with its thread pool.
So, the question is: what triggers things to go in the queue?
If the trigger is a user event (e.g., menu choice, button push), just have it launch an AsyncTask, or have it have a Service launch an AsyncTask. That work will be queued up by the AsyncTask system.
If the trigger is the passage of time (e.g., we want to check an external server every 10 minutes), I would use AlarmManager and consider switching from AsyncTask and a Service to using an IntentService.
I have a priority queue in order to select first the important calls to the API.
My program have two services:
One calls the API when a message is added to the queue. The call to the api is made by an Asinc Task in this way:
messages.add(request);
new DownloadApiTask().execute();
The other service is updating the local database. For that, i have a loop in which i call the first service in order to get data from the API. The basic structure is:
while ihave data to updload
mFirstService.putMessage(request).
Fine, the problem is i have a rejected Execution Exception every X calls, I think it can be because i invoke the asinc task every time i take a message.
For that, i was thinking in force to the asinck task to check the queue instead executing it.
I hope you can understand my problem.
Thanks

Categories

Resources