How to decide whether to use ASyncTask or not in android? - 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.

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.

Which should I use Handler, AsyncTask or Thread?

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.

What is the correct control flow for getting a one-time fix on the user's location (via GPS)?

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.

When should a (potentially) longer tasks take place?

I've got 2 tabs in my app, one grabs my contacts and geocodes their postcodes, the other tab plots them on a map.
The geocoding process can be quite time consuming. What is the best practice for handling such length processes?
Should I have a loading bar when the app starts and do all of the geocoding then or should I force users to click a button to do the geocoding?
You should move any operation that takes more than about 200ms onto a separate thread, so the app doesn't lock up, and then from that thread update an indicator to show the user progress.
You need to learn about the AsyncTask class, it's absolutely central to writing responsive Android apps.
http://developer.android.com/reference/android/os/AsyncTask.html
It's a pretty straightforward wrapper than makes threading easy. Remember to STOP threads when they're not needed any more, e.g. in onPause().
I tend to put AsyncTask subclasses into their own class file (not as an inner class) and pass them an activity context as a constructor parameter, so the AsyncTask thread always has easy access to the activity to update the user interface (but NOT from doInBackground).
Some limitations of AsyncTask
http://foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html

Killing threads

I've created a class which is an extension of Thread. This class hits a web service and throws some data on screen. I don't care about persisting this data (the screen displays search results).
Currently, the user simply types into an EditText and clicks a search button. I'd like to take away the search button and implement something similar to Google's Instant Search where, as you type, the search results get updated.
This means, as the user types, the search parameters change. I want to be able to kill the currently running thread (if one is currently running) and spawn a new one with the new search string. How can this be achieved? Can I do it with Thread or will I need to use a new object?
This is more difficult than simply killing a thread. You can call interrupt() on the thread, but the thread will have to check its interrupt status periodically and self-terminate.
Secondly, you will not want to start a thread immediately on a user typing. You will quickly overwhelm the system with thread spawning. Implement a wait period of 100-200 milliseconds before doing the search so that you can be reasonably sure the user is done typing. Google's server can handle the load, but the handset won't be able to.
EDIT: to expand on my first point, threads can be difficult to cancel. In this case the event dispatch thread will need to somehow tell the running thread it needs to stop. You can use the interrupt facility built into threads, but it tends to be touchy as pointed out by this article. Instead, I would simply have a boolean variable that can be set to cancelled by some outside thread. The trick (like shown in that link) will be that you will need to periodically check if the thread has been cancelled, and if so you will need to manually abort.
The next problem you will run into is if a web call has already been made to some outside server. It will block in that thread until it comes back and the thread will not be able to kill itself. This could take several seconds.
So let's play this out - what if a user types a character, and your timeout period expires for whatever reason and a web call is made, then the user types another character where the timeout period expires so another web call is made? If your web calls take 5 seconds, then the first thread will continue to run, even if the event dispatch thread cancels it, for at least 5 seconds. You now have two threads making web calls.
Now expand that. What if a user does this and makes 4 or 5 threads? This is where you overwhelm the resources of your handset. I am not telling you not to pursue this, just trying to point out the potential problems that come with the territory.
Use the AutoCompleteTextView widget. prefetch your search hints from your web service to load them into the autocomplete array and set its adapter. optionally use a custom cursor adapter depending on how complex your hints are.
something like:
AutoCompleteTextView inputSearch;
String[] autocompleteArray = new String[size of prefetched items];
//fill autocompleteArray with webservice data
inputSearch = (AutoCompleteTextView)findViewById(R.id.inputSearch);
searchAdapter = new ArrayAdapter<String>(context, R.layout.autcomplete_dropdown, autocompleteArray);
inputSearch.setAdapter(searchAdapter);
R.layout.autocomplete_dropdown could look something like:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/name"
android:singleLine="false"
android:textSize="15sp"
android:paddingLeft="3dip"
android:paddingRight="3dip"
android:paddingTop="15dip"
android:paddingBottom="15dip"
android:textColor="#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
do your searching in the app, how large is the content you will be searching? pre-load all the data in sqlite and check for updated data from the web every so often perhaps?
otherwise i'd say you should limit the amount of times your app tries to start a thread. setup some sort of timer that will:
see if...
a thread is already working
the input has changed since the last
time or has a non-empty search value
the user is even on the search
screen
if everything is OK, start up a thread to get results
just a thought, haven't tried this
Thread creating is very consuming operation. Thus I would recommend have one thread which will subsequently call webservices with new search strings.
What you mean is Auto Complete. I don't think you need to start a couple of threads to handle that. Work with android Auto Complete and use AutoCompleteTextView.
Furthermore it is not recommended to use threads by subclassing java thread or implementing the interface. You can use AsyncTask to perform time consuming operations in the background.

Categories

Resources