This question already has answers here:
Android AsyncTask - Order of execution
(6 answers)
Closed 7 years ago.
I'm writing an app that does the following:
Parses a webpage and extracts image URLs from it
Decodes them to Bitmap and shows them in an ImageView
I don't want these to run on the UI thread and obviously the 2nd point can't be performed without the 1st being completed.
Can i chain AsyncTasks to achieve this? I mean starting the second one from the first one's onPostExecute() method.
Is this considered bad practice? If so, how should i do this?
(this is a theoretical question, i'm not asking for code)
You can definitely do that and there is nothing wrong with chaining multiple AsyncTasks if you really have to. And I want to emphasise: only if you really have to.
AsyncTasks bring a certain overhead with them. If you chain two AsyncTasks you get twice the overhead. You don't want that. You should use the least amount of AsyncTasks possible.
In your case the solution actually seems quite simple: Perform all of the work in just one AsyncTask. Ask yourself: Is there really any need for two separate AsyncTasks? From your description it certainly doesn't seem like it. If you just use one AsyncTask your code will run a lot more efficiently than if you use two.
Please note that AsyncTasks should only be used for short operations that take a few seconds and which are started in response to a user action. If you need to perform some long running operation in the background than an AsyncTask is probably not the best solution. I can't really tell from your description if what you want to do is something suited for an AsyncTask or not, but if the work you are doing doesn't fall into the criteria I described above you are probably better of with an alternative solution.
Can i chain AsyncTasks to achieve this? I mean starting the second one
from the first one's onPostExecute() method
The only constraint is that the AsyncTask has to be instantiated on the UI Thread. As long as you instantiate it on the UI Thread you should be safe. So the answer is yes, you can do it.
If so, how should i do this?
There are different approaches to solve the same problem. You could use an ExecutorService for instance, and a Delegate/Listener, an Observer or a BroadcastReceiver to notify the completeness of a task
There's a good answer for this here but since you're asking theoretically, I'll tag an opinion onto the end of it.
From the AsyncTask docs:
AsyncTasks should ideally be used for short operations (a few seconds at the most.) 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 package such as Executor, ThreadPoolExecutor and FutureTask.
Chaining of Futures (or Promises) is a perfectly normal asynchronous practice. Future A does something and returns a value; this value can then be consumed by another asynchronous chunk of code, and so on, forming a logical processing chain.
In pseudo-code, it looks like this:
Future( calculate and return x).map( consume x and return y)
.map ( consume y and so on)
Of course, you can. Theoretically, this logic you talked about above can't be wrong. But, you have to understand that: onPreExecute and onPostExecute are called on the Main Thread, namely the UI Thread while doInBackground on another non-main-thread. Meanwhile, if you executed the second AsyncTask on the doInBackground of the 1st one, onPreExecute and onPostExecute of the 2nd one wound not be run on the Main Thread. Take notice of that.
Well, I don't think it is bad practice. The only downside I can see is that code becomes a little more difficult to read, especially if you end up chaining a lot of callbacks.
Related
Actually a basic Java question which I did not come along when I was learning this programming language.
For best understanding my question I will provide a simple sample:
block of code {
-new AsynTask..
-some code which I want to execute after AsyncTask finishes executing..
}
I know I can put the second line of code in postExcecute in AsyncTask object. But is it possible for program flow to continue after AsyncTask is finished executing?
You don't want to do this. This totally destroys the purpose of using an AsyncTask- it will halt the original thread until the task is done, preventing it from doing other things. If you wanted to do that, you'd be better off without the task. Instead, you should put the code you want to execute after the task is done in the onPostExecute method of the AsyncTask.
My Main thread seems to be pretty bad with performance. Transitioning between activities results in significant delays. I have pushed all of Web/Bitmap/File work into AsyncTasks and yet this is still happening. I have been doing my head in trying to figure out what is causing the slow-downs.
My question is - If the Main thread uses a class (say ImageDownloader) that creates its own little AsyncTasks (say ImageDownloadTask), will Main wait for ImageDownloader to finish it's AsyncTasks (hence delays?)
I would love to post code, but it's a very large project. If there is anything specific I should look for, please let me know and I'll be sure to share.
If you haven't already done so, I recommend you enable strict mode and look for activity on the main thread that way.
Check your onCreates and onResumes for anything that might run for more than an instant. This includes network calls, database calls, loops that may have a lot of iterations, and even reading from locally stored files (SharedPreferences read from an xml). Also try to benchmark how long your onCreate executes the setContentView method -- I believe nested LinearLayouts cause significant performance hits especially in complex UI structures. Acquiring a location with the LocationProvider, when not done properly, will also cause severe performance issues.
You may think you are fine with passing off long-running threads on an asynctask, but you also need to check that prior to starting these tasks, the data you need to start them may take a while to acquire.
I have a class currently called Promise that works as follows:
It holds a future value
It can always accept a subsequent action to take that uses the future value as the parameter
When the value is completed the function queue launches
Any functions added after the future is complete happen synchronously
So this seems to be a design pattern from functional programming that we're jamming into Java. The important thing is that we can daisy-chain on delayed events, which I understand is a feature more built into C# 3.0 language but you have to hack together with Java classes. Unfortunately, one, I don't know a better name for this than "promise" or "future," which seem misleading since the focus is more on the "DelayedCallStack" then the value at hand, and two, I don't know of any way to do this beyond writing our own fairly complicated Promise class. Ideally I'd like to lift this from the functional Java library but the concept eludes me thus far.
Note Java doesn't even give language/library support for an asynchronous callback that takes a parameter, which is one reason I'm so pessimistic about being able to find this.
So, what is this pattern, can it be done in libraries?
Take a look a ListenableFuture in Guava:
http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained
ListenableFuture allows you to add callbacks to be executed when the Future computation is completed. You can control what thread pool the callbacks get executed under, so they can be executed synchronously or asynchronously.
I can only say that we implemented pretty much exactly the same thing in Flex (ActionScript) and we also called it a Promise. In Clojure a promise is something quite a bit more lightweight: the get operation on it blocks until another thread delivers the promise. It's basically a one-element queue except that it retains its value forever, so subsequent gets always succeed.
What you have is a kind of a promise coupled with observers of its value. I'm not aware of any special term covering exactly that case.
EDIT
Now I notice that your "promise/future" might own the code that produces its future value (at least it's not entirely obvious whether it does). The ActionScript implementation I mentioned didn't do that -- it behaved like Clojure's, the value being supplied from the outside. I think this is the key distinction between a future and a promise.
Aren't these competitors? I'm thinkin they're not, but don't see it.
How about within the context of an Activity needing to learn when a Service has new xyz?
Thanks!
They are for different purpose so you can't compare in the way that one exclude the other as perhaps you may intend. I explain:
Registered Observers receive notification of a change all together sequentially simply calling once notifyObservers(..).
Handlers allow you to modify UI components from a background thread but you handle/update only 1 "observer" (the one handled by the Handler).
More advanced, if you think, you can even combine the two, to always be exception free while update UI from a background thread still keeping the Observer pattern.
I think nobody answered you in these 5 years because almost nobody is aware of great power of Observer pattern ;-)
I'm designing a system in java which utilizes a dns lookup class.
My question is, when calling the class's dnsLookup(), whether to do it in a new thread or use the observer pattern and let the dns class tell me when it's done.
This isn't a problem as long as the lookup returns a value almost instantly but when it takes a few seconds (when it doesn't get a response), I don't want to freeze the GUI while waiting.
So, new thread or observer. Appreciate some good links on the subjects as well.
Thanks beforehand - Dennis
You will have to employ both the observer pattern and more than one thread. There's no way to have the DNS invoking callback method in the same thread.
Your GUI is an event driver system so asynchronous notifications are good.
On the other hand, it's a lot easier to do network I/O (particularly if it's just a single DNS lookup) if you use synchronous (blocking) network calls.
Hence I would tend to go for the separate thread option, but then have that thread notify the main GUI thread when it's done.
Since it's a GUI that is making the call, I think it's best that you off-load the call to a different string. In fact, you want to make sure that you're not using the AWT-Thread to make a call that is blocking the GUI from refreshing. I would suggest using something like an ExecutorService to execute your commands and then upon the return, use SwingUtilities and call the invokeLater(Runnable doRun) method to update the GUI with the response.