How do I ask Robospice when pending requests are completed? - android

I'm using Robospice. I want to write some reusable code to stop ProgressBars and ProgressDialogs as soon as pending network requests have cleared for the current activity. However, I'm running into a couple of problems.
I'm watching when requests have completed by instrumenting a custom SpiceServiceListener to call my custom callbacks implemented within each activity. During onRequestAdded(), I show any Progress UI element. During onRequestSucceeded(), onRequestFailed(), and onRequestCancelled(), I check getSpiceManager().getPendingRequestCount() to see if it reaches zero and then hide any Progress UI elements.
The pending request count never reaches zero in my app (at least inside these three methods), but it seems to stop at one. This is true even though I can see from the Retrofit logging that my requests all appear to be completed.
Is the pending request count global or is it specific to the current Activity and its spice manager instance? Is there a better method to watch for all requests finishing within the current activity?

I have an answer. I missed instrumenting onRequestProcessed(), so the number of pending network requests never appeared to reach zero. The pending request count now does reach zero.
I still don't know if the count is global or local to the current activity and its SpiceManager instance, but I'm getting useful results from my new code.

Related

Is there any point in using Asynctasks for api calls that require a response to proceed?

I feel that the answer to this question is too obvious, but part of me still wants to ask it anyway.
I am creating an Android app that makes several HTTP POST/GET requests using APIs when the app is launched for the first time by the user. All these requests are made by launching Asynctasks within the activity.
For example, there is an activity where athe user has to select an item from a list retrieved from the API. After he selects one, a progress bar is displayed to the user while the app sends the selection to the API to retrieve another list, and in the next activity, the user selects items from this list. Clearly, the user can't go this second list until a response has been received from the server after the app sends it the first list's selection.
In such a case, is there any point in using an Asynctask to send the selection of the first list, since the user is prevented from doing anything (by being shown a progress bar) until a response is received and the next activity is started. Wouldn't it make the code less complex if I just made the API call on the main thread?
I hope this wasn't too confusing.
Thanks
I got your doubt completely. Good question. The root cause of the doubt because you are thinking you don't need to interact with the app till the process completes. But you actually want to. Event the progress bar will freeze if you could do something like it.
Ok, let's just assume you don't even have a ProgressBar. However, handling the different UI components such as Spinners, EditTexts is not the only duty of the main thread. It should define different callbacks in the activity lifecycle. Doing big tasks in main thread will also freeze callbacks like onPause(), onStop() etc. That is why the 'NetworkOnMainThreadException' is being thew.
Basically you cannot call the api on main thread as it will block the UI. Also now Android does not allow it to happen and throws 'NetworkOnMainThread Exception'. Its fine to use Asynctask for any task that takes few seconds and you get the callback in it , which in your case is required before you proceed to next screen.
Best way to do it is by using Networking libraries:
Refer this
https://developer.android.com/training/volley/simple.html
First of all you cannot do netwok call on main thread, it will raise NetworkOnMainThreadException , You can still by pass this exception by adding the couple of following lines in your activity
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
but it is always recommended to perform network operation in background,
else it may cause your app to stop responding, and can result in the OS killing your app for being badly behaved , go through this article once link
Any operation that takes more than a few seconds to perform should be added in a separate thread. All network operations should be performed on AsyncTask or do have a look at RxJava and RxAndroid. To be specific to your operation, any UI Operations during a network call can be performed in onPostExecute. If you're working with thread class then use a Handler.
As others mentioned, if main thread is used for network operation, it would make your app unresponsive.
User may want to start a different flow in your app by starting an activity from menu or action bar whatever is available in your app to start other flow.

Android - API Request Callback after onDestroy

I hope I can explain this well ...
I am trying to understand better how to handle HTTP callbacks in Android, so I have created a simple app that uses Volley for HTTP requests. It only has a button that triggers an HTTP request to a service that, basically, just updates a number in a database and sends it in the JSON response after 5 seconds. The Activity gets the response and displays the response in a TextView. I am testing it in a real device that has enabled the "Don't keep activities" option in Settings - Developer Options.
This is the scenario I am testing:
Start App.
Tap the button that triggers the HTTP request.
Inmediately after tapping the button, tap the device's home button to send the app to background. onDestroy method is called because of the "Don't keep activities" option.
Wait a few seconds for the HTTP response. I can see the device gets it because it is printed in the logcat monitor and the database is updated.
Before running the callback, I check that the activity is still alive. Since the activity has been destroyed, the callback is ignored. If the app is restored from background, there is no crash but the Network Response is missed. Also, if I tap the button again, it sends a new HTTP request and increases the number again ...
So, the questions are:
Which are the best practices to deliver network responses to the UI? I mean, if instead of a simple operation let's say it was a register form and I get a phone call or something that forces me to send the app to background, where anything can happens, how can I make sure to not miss the network callback? Is there something that could delay the callback execution until the app is again in foreground?
Is there a way to save a Bundle like the one in onSaveInstanceState after onDestroy has been called and restore it when app is again in foreground?
Let's say the information that the HTTP response contains is sensitive. Is there a recommended way to handle this case? I was thinking to save the response in the internal storage and check for it when the app is again in foreground, but I don't know if it is possible to do that after onDestroy has been called, or if it not a good idea with sensitive data.
Thanks in advance!
1)YOu can never miss the network callback. You'll be called even if you're in the background, unless your entire app (not just the activity is killed). You'll just get the callback while backgrounded.
2)No. If you need the result of a network call the next time the activity starts like that, I suggest you use a Loader to load the data. That way you can query for the Loader results next time, and start the request only if needed.
3)Do what I suggested in 2 and there's no need for this question, its all in app memory.

Robospice and potentially multiple pending requests

I'm using RoboSpice and I'm trying to reconnect to pending requests upon rotation. I'm doing most of the RoboSpice work in a fragment. I'm trying to figure out how to detect which pending request got connected.
Here's my scenario. I have two network calls that are executed in succession, let's call them Operation A and Operation B. I'm displaying a indeterminate progress bar saying something like "Performing Operation A" and "Performing Operation B". This is all fine.
Upon rotation, I'm trying to reconnect to the two potentially pending request, but not sure how to figure out what to display in my progress bar details. I can only detect misses, but not successful attachment to pending requests.
Any ideas on how to do that? If I use a generic message like "Loading..." in my progress bar, then I guess I could go with a synchronized reference counting type approach where I hide the progress bar if it ever gets to zero, but I was hoping there's an easier way. Any thoughts?

Android AsyncTask get() form another AsyncTask()

Background
I have an AsyncTask (call it uploadHeader) that uploads some data to a server.
I have a second AsyncTask (uploadDetail) that uploads some related data, which requires the initial data to have been uploaded: the header upload returns an id issued by the server, which is used to update the local detail records, before they're uploaded.
If at the time uploadHeader was initially called there were connectivity issues, the header info won't have been uploaded.
So at the start of uploadDetail.doInBackground() I check the status of the local header record to see if it has already been successfully uploaded to the server, and if not, call an uploadHeader.get() to upload the header and wait to get the id back, before I upload the detail records.
Problem
It just seems to hang at the get() call. Debugging it, it seems to be creating a FutureTask and then looping somewhere inside that. It looks as if the second AsyncTask is being queued to run after the first one finishes, which it never does since it's waiting on the second.
I've read a number of other posts/articles on calling one AsyncTask from another, but they all seem to be focused on getting the two to run in parallel. I want this to block, until the other task finishes. It's also been mentioned that "execute(Params...) must be invoked on the UI thread.", none of the articles mention get(). Or is get() basically identical to execute() apart for waiting for the result?
As a workaround, I could put the http call to upload the header in a separate class and call that from both uploadHeader and uploadDetail, so uploadDetail wouldn't need to create an uploadHeader task.
I'd just like to understand why it's not working as it is.
get() will block your execution until the second AsyncTask returns a value, don't do this if your first AsyncTask is doing some work that repercutes on the user interface of even in the workflow you've designed.
I'd definitely use Handlers on both AsyncTasks to communicate between them, even another one for the UI if you need to. You may find a good example here. For reference, look here.

Using Google Analytics with Android - Data Usage

I've just added the required code to my Android app and released the update to market.
Thinking about it though, I wondered what the data usage was like. Analytics doesn't send the tracking data immediately, instead it sends cached data at a set time interval or manually with a call in your app.
In my app I do this every minute. I don't think this is excessive as my app probably won't be open for long periods of time between uses.
I have three activities in my app that each track as a pageview. If the main activity is loaded it is tracked once. If nothing happens (i.e. no reloads or loads of other activities) after this one tracked pageview, will it continue to send data or will it know nothing has changed and therefore only send further data when more pageviews are tracked?
Cheers
Google's library works on a queue system. That being when you activity is loaded you have a call to track that page view. That single call will place a page view on the queue. Your timing code will take everything out of the queue and send it to the server. Once it's sent there is nothing left on the queue and it won't send anything when executes again in a minute. As long as there is nothing in that queue the polling cycle will look at the queue see there's nothing and go back to sleep waiting for another minute before checking to see if something new is there and repeating.
If the user shuts down the app and reloads it. Then the code will execute that page track statement again putting something back on the queue, and then it will send another page view.
It's important where you put that page track statement so that it sends it once per start and not during resume() or some other life cycle method that could be executed lots of times as the user jumps between views.
It won't keep sending the page view over and over on every polling cycle of your pumping thread.

Categories

Resources