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.
Related
I've been reading that we dont need to use AsyncTask when working with volley. I had a question though, one of the button click in my activity triggers a HTTP request. Now in case my app is closed, will volley still be able to process that request.
When I launch my app again, is it possible to figure if my previous HTTP request was sent or not.
What would happen to the response? Will I be able to catch the response and maybe make some db updates (local to app)?
What is the right design to do these kind of http requests?
Also, in case I want to make some HTTP requests while the app is not launched, can I not use a background task to do all this with volley?
You don't need to use an AsyncTask or Thread for Volley because Volley does that for you. So that's correct.
When you say your app is closed- do you mean the app is in the background, or the app is terminated? In the first case, the request will continue. In the second, it will not, and any response coming in would be ignored at the OS layer because there's no listening app on the socket. Also remember that apps not in the foreground can be killed by the OS at any time.
You can't send an HTTP request when your app isn't launched. You can do so in a JobScheduler or WorkManager item, but then your app is launched, you just aren't showing a UI.
In my phone when minimize aplicatoin then the Android destroy activity.
In Developer options I turn "Don't keep activities".
I try to implement MVP.
I have a activity with button.
Steps:
User click button
As result activity call method from Presenter: presenter.dowanloadFile(). This is a async http request. The size of file is about 10 MB.
Show progress
After 10 seconds user get success http response
Presenter call method from view: view.hideProgress
OK. This case work fine. Nice.
But suppose the next case:
User click button
As result activity call method from Presenter: presenter.dowanloadFile(). This is a async http request.
Show progress
After 2 seconds user minimize application
As result activity is destroy (because turn Don't keep activities)
After 3 second user return to application
As result create new activity
After 5 seconds user get success http response
Presenter call method from view: view.hideProgress
The question is:
Is I need to continue http request when user minimize application (item 4). Or I must cancel current http request. And when user again return to application I must again start new async http request?
I want the next: When user return to application and if http request success finish then to show result. If the request is not finish then continue to wait http response.
It depends on what you want to happen? It seems like it's wasteful to cancel a request that is expensive (10 seconds is a lot), however you also need to consider what "cancel" mean in the context of an HTTP request.
For example, if cancelling a request, only prevents results from being delivered. Than means that your file was actually uploaded but you don't get callbacks anymore for that request result. Also be careful if your upload thread has a reference to your view, it will be leaked till the upload is done.
If you don't really care about the request, you can just cancel it. Assuming your server is smart enough to identify another request for the same file, so you don't duplicate it if your activity was re-created.
Another option would be not cancelling the request. Then you would need some mechanism of having your "presenter" survive the Activity re-creation.
There are numerous ways of doing that:
Having a cache for your presenters and not re-creating it if it exists in the cache.
Using headless fragments, which are basically are fragments with setRetainInstance(true) to survive an activity re-creation.
Moving your upload logic to a background Service or JobScheduler, and having your presenter/view only subscribe to the state of the upload process, but not actually own it.
You can investigate each option individually when you decide what is the most convenient for your application.
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.
I'm making a login post request from android phone.
Returned result will be 'success' or 'fail'.
I can make this post request using either a IntentService or an Activity, both will work fine.
Case I'm concerned about:
Phone rings (activity paused/destroyed) before receiving the result from the web service.
Will I miss the result in this case?
I want the result of web service to be saved even if the activity stops before accepting the result.
Is there anyway it'll work using Activity or do I need to receive the result using an IntentService ?
It should be on the service, the best way of finding bad behavior like this is to enable strict mode on your application.
If you put it on the activity it will block the activity.
Any request sent from the Activity results in NetworkOnMainThreadException being raised - you must not call any http request from UI thread (How to fix android.os.NetworkOnMainThreadException?)
Delegating the request to IntentService and notifying Activity via Broadcast (opitionally prioritized Broadcast to handle cases when your Activity is in background while the Broadcast is delivered to the receiver) is the easiest approach I think.
Alternatively, you can use AsyncTask but you must handle screen rotation and remember about task cancellation.
You can extend AsyncTaskLoader and provide your custom loader but you still must remember about request cancellation (http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html).
An third-party open source, maybe? OkHttp allows you to execute asynchronous Http requests. In addition there is a cancel() method on a Call object which executes the request. Thus, you can easily use it in the activity
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/com/squareup/okhttp/recipes/AsynchronousGet.java
Indeed, the StrictMode is a good tool that validates errors during development.
I have written an application that queries a web service I wrote (which returns JSON data). My app currently processes the web service call using an AsyncTask and updates a TableLayout with the data it receives. I want my app to regularly (every second or so) call this web service and display the data in the DB, as it is continuously being updated. How can I go about doing this without having the UI thread block?
Currently the way things work is the user presses a "go" button, and the AsyncTask displays a "loading" dialog while the request processes. I would like for them to press the go button once and have the data refresh in the layout. I'm not sure what the best way to architect this is.
I wouldn't recommend that you create a new AsyncTask every second since this is going to result in a lot of object creation and corresponding memory collection.
What you can do instead is create an AsyncTask that after each request returns from the web service updates some internal data structures and then calls publishProgress(), waits the appropriate amount of time, then makes a new request to the web service. In onPublishProgress() the code should then get the new information from the request from whatever internal structures are being used (don't forget to use a lock here to synchronize access) and refresh the UI.
You'll also want the AsyncTask to have a method or variable that the Activity can call to tell it to break out of the loop.
You can use a Handler which can initiate a new AsyncTask request after every second.