Within an AsyncTask, I am making a REST call to retrieve data. Within that AsyncTask, I may encounter an exception which I would like to package up (the HTTP code) and inform the Activity, which based on the HTTP response code (Timeout, Unauthorized, etc), would display different messages to the user.
What would be the best way to bubble that information up to the Activity for processing?
I have looked at a number of different Android mechanisms such as Notification, Handler, etc but I can't seem to determine a good architectural pattern for this situation.
If the error causes a halt in the users workflow, then you need to obtrusively interrupt using a dialog alert and then direct the user to the fix. If the error does not stop the user, then interrupt unobtrusively using a toast or notification.
Related
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.
I have a language translation app that needs to download some initial data on the first run. When the app is first launched, the first step is to get a list of currently supported languages from the server. The user then selects which they wish to install, and the rest of the tables are then downloaded.
I check if the languages are present in the local db, and if not, connect to the server and download them as JSON. The user cannot do anything until this data is retrieved from the server.
If there is no network connection, a dialog should prompt the user to go to their WIFI settings. If there is a network error with the download, another dialog would then prompt the user to retry now, or wait until later. If the download succeeds, a new Intent is launched to send them to choose the languages to install.
I have this mostly functioning (my AlertDialogs aren't showing), but the question is whether this is the proper way to accomplish this. I've currently set it up as an AsyncTask, but I've seen plenty of posts with responses yelling about how an AsyncTask should not be used when the UI depends on it. Fair enough, but an AsyncTask seems to be the recommended method for downloading data.
Is an AsyncTask the correct way to download the data, or is there a preferred alternative?
How to best deal with this on the UI, as it depends on this data? A splash screen? I'd rather not, but it seems something should be there, and I need somewhere to display the AlertDialogs if necessary.
Is an AsyncTask the correct way to download the data, or is there a preferred alternative?
No, AsyncTask is not a good solution for networking because:
You need a component from where you start this task. Activity is not a good choice because your network request will be tied to the UI and it will be hard to handle screen rotations, etc.
AsyncTask works on a global serial executor by default. It will block all other async tasks in the app until it finishes. So you will have to provide your own executor to avoid that.
The process level would be Background Process according to http://developer.android.com/guide/components/processes-and-threads.html
With a Service you can achieve Service Process which is better.
Use Service instead. You can implement any threading you want inside. You can use a regular Thread, a ThreadPoolExecutor, a Handler, or some third party solution. Service provides you great flexibility.
Regarding your second question, take a look at material design spec first: https://www.google.com/design/spec/material-design/introduction.html
Come up with some ideas and then ask a separate question if that is still not clear.
I have a server running on some where and an Android application for end user. From Android application user can delete message, and this delete message will trigger sending a delete request to server through REST and server will delete it.
Does anyone know how the gmail's delete message works? Even if I quit from app or move away from app the send, delete or other operations completes eventually. Are they using AsyncTask or Thread or Service. I guess its not AsyncTask since user can move away from current view or can move away from whole application.
any suggestion is appreciated.
You may want to look at IntentService.
http://developer.android.com/training/run-background-service/create-service.html
"The IntentService class provides a straightforward structure for running an operation on a single background thread. This allows it to handle long-running operations without affecting your user interface's responsiveness. Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask"
I'm not sure how Gmail's REST API works, but for REST calls, AsyncTask is definitely not the way to go. Why reinvent the wheel? Take a look at Volley or RetroFit. They are both REST libraries that take into account a lot of pitfalls one encounters in implementing REST calls in Android.
currently I have an app that creates all sorts of different requests to Facebook and my server, and I was wondering if the best way to do this is implementing a different AsyncTask or using the same AsyncTask for all the different requests.
what do you think?
Here is a use-case for instance:
I send a Facebook connect request, when I get to onComplete, I get the users Information with FQL (has to be Asynchronous) , when the response comes back, the user's image is posted on the main view.
After this, the app sends a different request to the app's background server and gets a response.
I think you must decide it for yourself.
If you have lots of requests beware of the android's limitation of number of AsyncTasks. If you hit that limit your app will crash.
Also notice that if you assign many jobs to a single AsyncTask you could have a very long running task on the background.
You can also read this article -> The Hidden Pitfalls of AsyncTask.
I'd suggest to use concurrent AsyncTasks to ensure all the other requests are run in case one of them won't return an answer.
I'm looking to find the "correct" way to get a fix on the user's location as a one-time task. At the moment, my execution flow is roughly:
The user presses a button.
The handler (contained in the main Activity code) registers a GPS location listener with the system, set to update as fast as possible, launches an ASyncTask, and finishes.
Pre-execution, the ASyncTask generates a ProgressDialog, effectively blocking any other UI usage.
For it's background task the ASyncTask waits for either a timeout or for a location fix for the GPS.
Post-execution, the ASyncTask either displays some relevant data to the user if a location was found, or displays an error in a toast if it was not. It also de-registers the listener of course.
Now, while this works, there are numerous downsides. Firstly, and quite obviously, all other UI interaction with the app is blocked while a request is being made. This isn't too bad currently, as the app's main function is to perform this task, and there isn't much else to do while it's working - it also stops the user from spamming the button. Additionally, I'm not sure if the post-execution phase of the ASyncTask is really the place to put my location-found logic (it makes an internet call, which is something that itself might be better off inside an ASyncTask?). However, I'm not sure how else to pass back the fact that a location has been found and that the main thread should do something.
I was hoping that someone could inform me as to the "right" way to do this - i.e. is using an ASyncTask like this correct, should there be a Service involved, and how should I deal with the internet-call post-location-found), and perhaps even give some wise words on how in general to deal with the control flow of an app which has to make somewhat "blocking" calls.
I can provide code if needed, might take a bit to get it cut down to a minimum solution.
Blocking calls and blocking UIs are generally to be avoided. See Reto Meier's take on the subject.
Hence, I'd dump the AsyncTask entirely. Disable the Button that the user uses to kick off the fix request. Use a postDelayed() Runnable for your timeout mechanism. And, allow the user to do something (read help, etc.). Use the progress indicator in the title bar to indicate that you're working on getting the location, dismissing the indicator when you get a fix or when your timeout occurs.
(it makes an internet call, which is something that itself might be better off inside an ASyncTask?)
It certainly should not be done on the main application thread. When the location fix comes in, kick off the AsyncTask to fetch the data.