Which should I use Handler, AsyncTask or Thread? - android

This may be a common question but I couldn't find my exact scenario. I understand that its down to developer choice in a lot of ways but I don't know enough to choose best.
I have my initial app splash screen which will just display a logo whilst checking the user is logged in. If their login details are already stored in a sharedPreference then I want to check those details against my online database of details for verification. Once this is all checked I'll either pass the user through to the main app screen or a registration screen.
So when doing this check of user details, and then verifying them. Should I do this in a separate or use a handler? I don't think AsyncTask is needed as I'm not wanting to pass any progress details back to the UI?
TIA

I suggest using AsyncTask.
First of all, because AsyncTask is a complete threading framework (that uses Thread and Handlers behind the scenes) that allows for a nicer control of single thread operations. Including cancel() for example, in case the user decices to leave the application before the splash screen is done.
I don't think AsyncTask is needed as I'm not wanting to pass any
progress details back to the UI?
actually, yes you do, even to start the new activity (either Login or AlreadyLoggedIn) you have to call startActivity() from the UI thread

You should probably do this in a separate thread because it is network activity. IntentService is a good option. I think your main concern is that whatever method you choose needs to work even if the user rotates the screen and the activity is destroyed and recreated.
Maybe use a Fragment for the splash screen with setRetainInstance(true), so it will get reattached to the activity after configuration change. Then you can either pass the service a Handler (or a Messenger to be more accurate), or have the service send out a broadcast intent when it finishes working.

When to use an Async Task?
AsyncTask helps in offloading memory intensive/blocking call to a background thread while, your UI operations can still carry on in the UI thread.
If any operation blocks the UI thread for more than 4-5secs, you might also get an ANR(Android Not Responding) dialog. AsyncTask come handy when you want to update the UI after doing the process (onPostExecute) and also before starting it (onPreExecute).
Using a Thread
Whatever you do in doInBackground using an AsyncTask can also be achieved using a Thread. But incase you need to do any UI operation you will need to use a Handler or runOnUiThread to accomplish your task. Refer to Painless Threading in android in case you wish to use threads.
Also what Budius said is true.
In your case you can use an AsyncTask to check for user creds in sharedPref and then appropriately authenticate with your middleware and finally in onPostExecute navigate to a new activity.
In the meanwhile you can show a progress bar to the user signifying the on going auth process.

To add on to that. I had a very similar situation where I had to verfiy a users login (which was stored in the phone) in the background from a "home screen". I used the IntentService ResultReceiver pattern. At first it took a bit for me to get up-to-speed on it, but once its implemented its very simple to manage.
Basically, you start the activity that is your intent service, passing it any parameters that are needed (username, password, etc...). In my case it was a separate class that used REST to verify the user. Once the REST class has done its work, the ResultReceiver method onReceiveResult, returns back the data to the UI activity from the REST activity.

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.

How to decide whether to use ASyncTask or not in android?

I have a simple Android UI. When user clicks Button, it takes the user's location and then it goes to 4-5 websites and gets all the events in that hour. Then, according to the user's location, it compares the closest ones, and according to a radius given, it shows the event names in a new screen.
After clicking Button, it will go into another screen and will write something like searching for location or progress dialog, or location identified. After that, it'll show the events to the user. So, should I create 3 activities and 3 screens?
According to this link
how to use method in AsyncTask in android?
He says don't prefer AsyncTask for long network jobs.
I can't use location methods inside AsyncTask. Before executing I should send location as parameter. But again, computeDistance method needed. At post execute method, I can post events to new UI.
But when the user clicks these events, from onClick I can do jobs but I can't find or retrieve info of these events.
I decided to use AsyncTask after commenting somewhere here and someone answered me to use but I can't find that post.
And now i am unsure about to use or not.
I need webconnections, so I don't want to make them in main. So it is good to use AsyncTask for that but is it necessary?
This is what I would recommend:
Use AsyncTask. It will run a background thread and give you a way to display progress in the UI thread as each website is checked. This isn't a "long network job" compared to, say, streaming a video. IMHO, using a Service for something like your operation is just too heavyweight. So start out with an AsyncTask.
Once you have that, however, you will discover your next problem, which is that your web operation might take long enough that if you rotate the device, the Activity will be torn down and recreated in the new orientation. Then when your AsyncTask completes, the Activity it was supposed to call back to is no longer there. Oops, now your user doesn't get their results.
The best solution I have found for that is to use a special fragment to "host" the AsyncTask. This fragment will not create a view and use setRetainInstance(true) to keep the fragment alive during Activity re-creation.
You can read about this novel technique here: Handling Configuration Changes with Fragments
AsyncTask is an abstract class provided by Android which helps us to use the UI thread properly. This class allows us to perform long/background operations and show its result on the UI thread without having to manipulate threads.
Android implements single thread model and whenever an android application is launched, a thread is created. Assuming we are doing network operation on a button click in our application. On button click a request would be made to the server and response will be awaited. Due to single thread model of android, till the time response is awaited our screen is non-responsive. So we should avoid performing long running operations on the UI thread. This includes file and network access.

Avoiding IllegalStateException “Can not perform this action after onSaveInstanceState"

This topic has so many different SO questions linked to it, I know, but I think most people ask their questions while still confused about why things happen when.
I've read Alex Lockwood's article on Fragment Transactions & Activity State Loss, and although he provides clear arguments for all things (read the article - it's really informative and easy to understand), he doesn't provide a full proof work around for my situation - using AsyncTasks.
Here's what we do in our app:
User presses a button which initiates an AsycTask doing a call to our server.
A phone call is initiated from within the app using Intent.ACTION_CALL.
Phone call is ended and user returns to the app.
AsyncTask responds with server call response.
App code processes the response and displays output to user.
So obviously, when the user goes to the phone call, our app is stopped. So when the AsyncTask gets to onPostExecute() and provides the server call response, we might not be in a live activity, and it's probably after onSaveInstanceState() has been called.
So how do I solve this?
I have to communicate the results of the server call response to the user through an AlertDialogFragment, but when I want to show that alert, I get IllegalStateException.
Alex Lockwood suggests that I make sure that no fragment transactions occur after onSaveInstanceSate() has been called - i.e. (I figure) don't trigger anything in the app (like displaying an alert), from the onPostExecute() of an AsycTask.
So when then?
Should I do something in onResume() like check there whether I've received a response from that AsyncTask server call, which I should probably save to shared prefs rather than process and present results to the user, and if so, display that alert to the user?
Please advise?
An AsyncTask will still run after an Activity is navigated away from. This means that onPostExecute() may be called when an Activity is no longer visible and any UI changes that should be done in onPostExecute() will result in an Exception, most likely a NullPointerException or an IllegalStateException.
To remedy this, you will have to either manage the AsyncTask yourself by stopping it in your activity's onPause() and restarting it in your activity's onResume() or place the task in a retained non-UI Fragment. In my opinion, these solutions are a little hacky. I would highly recommend using an AsyncTaskLoader in place of an AsyncTask when the UI will be modified after the task executes. AsyncTaskLoaders use a LoaderManager which handles the Activity/Fragment lifecycle for you.
There are many resources that demonstrate the correct implementation of AsyncTaskLoaders, I have listed some of them below:
Android developer documentation
Alex Lockwood's blog post
Wolfram Rittmeyer's blog post
I used the AsyncTaskLoader class in one of my open source applications, CrimeTalk Reader, to load web data using Jsoup and put the resuts in a ListView. The class that uses it can be found on Github.
In instances where you want to run a long-running task without UI interaction, you may want to check out the IntentService class.

Android: How to retain AsyncTask instance when Activity gets destroyed?

In my app, I have a class that inherits from AsyncTask and which downloads huge amounts of data from the server. I am using a ProgressBar to indicate the progress of the download.
When the user hits the HOME key, the Activity to which this AsyncTask is attached, is destroyed but, download goes on.
How can I reattach this AsyncTask and show the progress to user? I tried using onRetainNonConfigurationInstance but Android 4.0 doesn't seem to invoke this method. My application does not use Fragments API.
What I did in this situation was as follows:
I created an IntentService to handle communication with the server. This has some of the benefits of AsyncTask (e.g., worker thread), but also some benefits of a Service (available any time, from anywhere).
The IntentService can be invoked either by a user action in my main Activity, or via an inexact repeating alarm.
The data is stored in an SQLite database, fronted by a ContentProvider. I dodge the issue of when/how to create my database and tables by using an SQLiteOpenHelper and calling getWritableDatabase() from the safety of my background IntentService.
When the task is done, it posts a Notification if my main Activity is not active.
One nice thing about this arrangement is, no progress bar is necessary. In fact, no UI is necessary. The user keeps using the application while the service is running, and the UI automatically refreshes itself as new data comes into the ContentProvider. Another nice aspect of it is it's less code to write than an AsyncTask. It automatically picks up where it last left off by reading the server-side metadata of the last entry from the database and asking the user to start after that point. Since it's not tied to any Activity instance, it doesn't care about onPostExecute() or configuration changes or any of that. And you don't have to worry about single-shot execution like AsyncTask.
If there is a need to download huge amount of data in background I would use service rather then AsyncTask. There is a good presentation from Google IO about using services.
Quote from AsyncTask documentation:
If you need to keep threads running for long periods of time, it is
highly recommended you use the various APIs provided by the
java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and
FutureTask.
and
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
As I understand, you cannot proceed with your last AsyncTask.
Still, you can load your data partially and save amount of data read and then start new AsyncTask which will start from last saved point. From my point of view this is not the best idea to pause loading when activity goes to background and it is better to use service to finish what was started.
Have you considered using a service to attach your AsyncTask to? Seeing as a permanently running service would probably be the best solution for your task at hand. All you'd have to do then will be to check if the service is running and if your download is running (easily done using static boolean variables) then you just create a progress dialog using some state saving variable in your service (maybe a percentage of the total file size downloaded etc.) in the onCreate method of your main activity.

Android app architecture - where to put REST API call code?

I want to better understand how to structure an Android app where an activity fires off an API call (for example).
I'd currently implement it by putting the API call into an AsyncTask subclass, passing it a reference to the activity so it can update the UI in onPostExecute. But my gut-feel is that this is creating overly-coupled code.
I'm wondering whether instead I should put an API call like that into a service, and use a BroadcastReceiver to update the activity.
What say you, AsyncTask, or BroadcastReceiver?
I usually follow the Local Service pattern. I have a strong suspicion that this is how the official Twitter app works and that this is the pattern most of the Google apps use. This also solves the issue of your app going away (getting killed or going into the background) before the task finishes, or if the phone switches configuration during a background task.
BroadcastReceiver and service is an overhead here. A request to web-service should not go to long. Service is appropriate in case of downloading files or something similar.
AsyncTask way is the right one here. But I would suggest you showing a progress dialog to let user know that your application isn't freezed, but doing some useful work.
See the example here.
AsyncTask is just fine. Only thing you should worry about is referencing you Activity using WeakReference to avoid whole Activity be memory leaked. It isn't overly-coupled code imo if you using observer or events patterns.
I would go with a service only if the call is going to take long, so that the user can leave the app while it's completing.
I'd use the AsyncTask if the task is short enough that it almost wouldn't go ANR if done in UI thread.
(disclaimer: I consider myself a beginner, and I'm expecting comments from more experienced people)

Categories

Resources