I have read the two reasons/issue mentioned on:(Please read two reason on below link)
Android AsyncTask for Long Running Operations
1. "If you start an AsyncTask inside an Activity and you rotate the device, the Activity will be destroyed and a new instance will be created. But the AsyncTask will not die":
Lets suppose i have set the orientation of my activity to Portrait. Will this issue still be there?
2. Memory leak issue:
inner class will hold an invisible reference on its outer class instance : the Activity.
What if i am not using Inner AsyncTask instead created separate class. Also if i use weak reference.
The issues you mention arise only when life-cycle of AsyncTask is not handled properly, mainly from lack of understanding of how they work.
AsyncTask is a wrapper for running code on a separate thread. It is similar to plain Java's Runnable submitted to ExecutorService, with additional features of "pre" and "post" hooks to be run on main thread. So, its basically an enhanced version of Thread, Runnable and Handler setup.
By default AsycTask's share a single thread and hence not advised for long running tasks. Because when a single background thread is shared by many tasks, a long running task may block others. However, AsycTask can also run on a custom Executor, removing such restrictions of a shared worker thread.
All that means that AsyncTask's own design doesn't restrict its usage for long running tasks.
You can have a background Service run some continuous processing using AsyncTasks on a separate ThreadPoolExecutor.
You can have a Fragment load latest news using an AsyncTask and when Fragment's onDestroy() is called, you cancel the task, since its no longer meaningful.
Hence the answer to "how long and AsyncTask should run", entirely depends upon the usage context.
Additional problem of AsyncTask: losing your results.
Yes, you said:
Lets suppose i have set the orientation of my activity to Portrait.
Will this issue still be there?
But, Activity could be recreated not only 'cause rotation. For example, if there is no enough resources in system, operation system can destroy your Activity.
So, for long running operations there is high risk that AsyncTask will have an invalid reference to its Activity in onPostExecute() after Activity recreation.
Another problem: parallelism.
new AsyncTask1().execute();
new AsyncTask2().execute();
Will these two tasks run at the same time or will AsyncTask2 start when AsyncTask1 is finished?
Well... It depends on the API level.
And aboud API level...
Before API 1.6 (Donut): the tasks were executed serially. This means a task won't start before a previous task is finished.
API 1.6 to API 2.3 (Gingerbread): the Android developers team changed AsyncTasks to make possibility to start them in parallel on a separate worker thread.
API 3.0 (Honeycomb): the AsyncTasks where executed serially again. Of course the Android team provided the possibility to let them run parallel. This is done by the method executeOnExecutor(Executor). Check out the API documentation for more information on this.
Setting the orientation will work because locking to portrait means no orientation change, meaning no lifecycle re-creation because of this. However if an activity is paused for a long time it can still be destroyed so this is not a good way to make sure this works 100%. You could instead try a service or a headless fragment.
According to this post, having a weak reference will solve the memory issue
AsyncTask have following drawback.
1. Memory leak :- In inner class as well in seprate class you provide reference of your activity to AsyncTask for callback in both case AsyncTask will not release the reference of activity for GC which cause memory leak.
2. GC :- If a AsyncTask is running although the calling activity is destroyed it will restrict the GC to not run till it will not finish its process.
3. On Orintation change activity recreate as Asynchtask will running in background and when it finish its operation it will try to update UI which cause IllegalStateException as activity is not attached to window.
So its better if you use Service for long running background process instead of AsyncTask.
There are so many superstitions around this topic, it's hard to know where to start. AsyncTask is just a small piece of sugar around a standard task queue, using it or not using it does not make much difference in comparison to other things.
For example the problem of orientation change is NOT real. You can start an AsyncTask when the activity starts for the first time and simply not start it the next time around. (and remember that other changes in configuration can also restart your activity).
The weak references are a total overkill and will probably get you nowhere. You either need a reference to the current activity (and then the weak reference won't work) or not (and then, simply don't hold any reference).
The most important, and missing from your question, is what are you actually trying to accomplish?
Think about someone answering their phone while your application is running, and going back to it after some time. And then try to answer questions like:
- are the results from 15 minutes ago relevant? Or will the task be restarted?
- how about 6 hours ago?
- will something bad happen if the background task is interrupted?
- does user expect the task to be finished? (did he press "OK" and just waited for a confirmation to appear?).
And then you can ask a more precise question. AsyncTask can be used in any scenario, but usually it's simpler not to use it than to use it correctly.
Related
I have following question. I am writing an app using location for android 4.4-6, and I decided to wrap determining location in a handy class.
Because determining location is an async process, I return unresolved future from method of this class, listen in this class for location events, and when I get location event with correct accuracy, I resolve settablefuture (from Google guava library)
this future is used in another class, because I perform few checks (accelerometer, and then proximity, and then location) and want to process it linear and future feels natural here (I am from JavaScript world and use java only as a hobby).
however it seems that this settable future, while waiting for being resolved it block everything, and event loop is also blocked so even if phone is determining location, method onLocationChanged is never called on my location listener. of course I register it in location manager. so after 10 seconds of inactivity I resolve future with null value and sometimes after that my location listener receive update (interesting fact is sometimes it happen after unregistering it, so it suggest that event queue is blocked somehow)
anybody knows how to resolve this issue?
Source code of this class in gitHub
You're using GoogleServicesApi, correct? You should consider utilizing the FusedLocationApi#requestLocationUpdates and update on regular intervals. Keep saving off each updated Location and then return the most recent whenever its requested. For example, have a class implementing the LocationListener which has a field
private Location bestEstimate;
and a getter
public Location getBestEstimate() {
return bestEstimate;
}
The problem with this approach is what to do when bestEstimate is still null (or Optional#absent since you're using Guava.) I will leave that up to you as to how to handle it.
You can go further with this and use SharedPreferences to persist each location update to decrease the chance of not knowing the location between app closures, backgrounding, and whatnot.
I didn't dive too deep into your code, but it appears that the UserRide#getCurrentSpeedKmhm method is called on the main thread. You should start up an AsyncTask to run it in the background. Then everything else will remain unblocked on the main thread.
As an alternative that may require less coding, consider using SettableFuture#addListener (http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/AbstractFuture.html#addListener(java.lang.Runnable,%20java.util.concurrent.Executor))
Finally I made it working.
It looks like I need 3 threads. 1st - UI thread (activity)
2nd - my AsyncTask where I ask for future and wait until it will be resolved. In this thread LocationUtillity returns unresolved future, and launch 3rd thread which will make all work. This thread get blocked by unresolved future, until it will resolved (result of the future is required later so thread must be blocked)
3rd - new Thread which will listen for locationUpdates. Because it's separate and it can listen for events, and when correct event come, it resolve future and by resolving future, and unblock 2nd thread which can proceed with it's calculation.
Previously with UI thread and async task it was working like this:
In async task, after registering to location updates, looper must be called. When looper.loop() called, thread gets blocked, and method returning future was not returning it, so rest of the program never executed.
OR
When I called looper.loop() after receiving the future, the location listener never received updates, because looper was actually called after resolving the future with the timeout value (which happens always after 10 seconds without proper location updates).
So the solution was to use three separate threads for every path of execution.
I am from JS world, here everything is async so it was unnatural for me that I need to create so much threads to parallelize it, I didn't know that all of this things should be separated in separated threads to not block each other.
I'm developing an app which must heavily interact with the server.So user input name and password and after authorization the next tasks must be performed:
The app has to fetch all incoming and outcoming messages for this user and load them to SQLite database.
Fetch all user friends (JSON with id,names,contact_data) and also load it to the app's database
Jump to the next activity and display income messages from the local database.
The problem this operations are too slow and when app starts new activity it is nothing to fetch from the database :AsyncTasks have not completed yet.I'm forced to use AsyncTask.get() in order to wait when they all complete but this takes over 16 seconds to wait!So what should I do: use threads, or before loading fetched data to database hold it in memory and display it in the new activity instead of fetching it from the database?But even without database tasks other fetching tasks take nearly 10 seconds to wait!So what should I do?
Oke a couple of things going pretty wrong here.
Do not use AsyncTasks for Networking. Use a service. In short, this is because your AsyncTask will stop, as soon as the Activity that started it will stop. This means that network requests get aborted easily and data goes lost and has to re-start again when the Activity is opened again.
Do not use .get() on AsyncTasks. This makes the UI thread wait for the task to complete, making the whole AsyncTask idea kinda useless. In other words: This blocks your UI.
What you should do:
Read up on using services. You can also have a look at a great opensource library called RoboSpice to help you with this.
Stop using .get() on AsyncTasks, if you want to know when it is done just use a listener.
Execute AsyncTasks on a threadpool ( myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); ) when possible.
You should use a Service. This way it always can complete the tasks it was doing and you can complete all your tasks. Besides that you should initialize the app once, and after that only update the data.. that can't take 10 seconds.. than you're having an other problem.. But the nice thing of the service is that this can run in the background. see: Services in Android Tutorial
== Edit
Also take a look at GreenDao This library arranges fast SQlLite operations. Without the large setup!
AsyncTasks are not meant to run several small tasks concurrently at the same time. Quoting the docs
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
Use Threads in a ThreadPool when you want to run multiple tasks concurrently.
How you want to handle this situation is up to you. When the background tasks take too long, you can always show an alert dialog to the user and then take them to the activity once the data has been populated. Many apps show a 'Loading' screen when this happens. You can also show the 'Loading' Spinner control if no data is available yet. Never show a blank screen.
If the server side calls are under your control, employ some sort of caching to speed up the time. Any API call that lasts more than a second will make for an impatient user. If not employ one of the techniques mentioned in the previous paragraph. #Perception's technique is also one to consider if you can do it.
I can't seem to find any documentation on the details of an Activity's run loop for Android.
Apple documents the "anatomy of a run loop", and that's pretty much what I'm looking for. The Android documentation just says "Activity Is Running" in its life cycle state diagram. Obviously that's backed up by some sort of run loop.
Anyone have some insight (aka Documentation) into the internals of an Activity's run loop?
edit - I should clarify that I presume the run loop is actually owned and run by the main UI thread. The current Activity's functionality is likely injected into this runloop at a certain point. I'm interested in the overall UI thread run loop, as well as what role the Activity takes in it.
The short answer is, "don't worry about it, it's done for you."
Activities and other constructs sit on top of android.os.Looper, communicating with it through instances of android.os.Handler. A Looper manages your "run loop," dispatching messages from a queue and blocking the thread when it's empty. Handlers communicate with a thread's Looper and provide a mechanism for working with the message queue.
Most of the time you won't need to work with either one directly. Lifecycle events for your major application components like Activities and Services will be dispatched to your code. If you're curious as to what's under the hood, sources for both are available:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/Looper.java
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/Handler.java
Updated:
There's really nothing specific being referred to by "Activity is running." The Activity is simply displaying its UI, handling input, executing any necessary functions, and starting another Activity.
If you're interested in what implications multi-threading would have on the run-loop, there isn't really a concrete relationship. Your threads can just do their work, and the Activity's state will function independently and automatically update its UI (provided you call postInvalidate() correctly).
Original:
Take a look at the first diagram on this page: http://developer.android.com/reference/android/app/Activity.html
It specifies the "lifetime" of each Activity and what states it can be in, if that's what you're looking for.
Can someone tell me the TRUE difference?
My rule of thumb is that an AsyncTask is for when I want to do something tied to single Activity and a Service is for when I want to do something that will carry on after the Activity which started it is in the background.
So if I want to do a small bit of background processing in the Activity without tying up the UI I'll use an AsyncTask. I'll then use the default Handler from that Activity to pass messages back to ensure updates happen on the main thread. Processing the updates on the main thread has two benefits: UI updates happen correctly and you don't have to worry so much about synchronisation problems.
If for example, I wanted to do a download which might take a while I'd use a Service. So if I went to another Activity in my application or another application entirely my Service could keep running and keep downloading the file so it would be ready when I returned to my application. In this case I'd probably use a Status Bar Notification once the download was complete, so the user could choose to return to my application whenever was convenient for them.
What you'll find if you use an AsyncTask for a long-running process it may continue after you've navigated away from the Activity but:
If the Activity is in the background when your processing is complete you may have problems when you try to update the UI with the results etc.
A background Activity is far more likely to be killed by Android when it needs memory than a Service.
Use Service when you've got something that has to be running in the background for extended periods of time. It's not bound to any activity. The canonical example is a music player.
AsyncTask is great when some stuff has to be done in background while in the current activity. E.g. downloading, searching for text inside a file, etc.
Personally I use Handlers only to post changes to the UI thread. E.g. you do some computations in a background thread and post the result via handler.
The bottom line: in most cases, AsyncTask is what you need.
To complement the other answers here regarding the distinction between service and AsyncTask, it is also worth noting[0]:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
Services tend to be things that describes a significant part of your application - rather than an AsyncTask which is typically contributes to an Activity and/or improves UI responsiveness. As well as improving code clarity Services can also be shared with other applications, providing clear interfaces between your app and the outside world.
Rather than a book I would say the developer guide has lots of good answers.
[0] Source: http://developer.android.com/reference/android/app/Service.html#WhatIsAService
AsyncTask: When I wish to do something without hanging the UI & reflect the changes in the UI.
E.g.: Downloading something on Button Click, remaining in the same activity & showing progress bar/seekbar to update the percentage downloaded. If the Activity enters the background, there are chances of conflict.
Service: When I wish to do something in the background that doesn’t need to update the UI, use a Service. It doesn’t care whether the Application is in the foreground or background.
E.g.: When any app downloaded from Android Market shows notification in the Status Bar & the UI returns to the previous page & lets you do other things.
Service
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with.
When to use?
Task with no UI, but shouldn’t be too long. Use threads within service for long tasks.
Long task in general.
Trigger: Call to method onStartService()
Triggered from: Any Thread
Runs on: Main thread of its hosting process. The service does not create its own thread and does not run in a separate process (unless you specify otherwise)
Limitations / Drawbacks: May block main thread
AsyncTask
AsyncTask enables the proper and easy use of the UI thread. This class allows performing background operations and publishing results on the UI thread without having to manipulate threads and/or handlers. An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread.
When to use?
Small task having to communicate with main thread
For tasks in parallel use multiple instances OR Executor
Disk-bound tasks that might take more than a few milliseconds
Trigger: Call to method execute()
Triggered from: Main Thread
Runs on: Worker thread. However, Main thread methods may be invoked in between to publish progress.
Limitations / Drawbacks:
One instance can only be executed once (hence cannot run in a loop)
Must be created and executed from the Main thread
Ref Link
Normally in a C or C++ program there's a main loop/function, usually int main (). Is there a similar function that I can use in android Java development?
As far as an Android program is concerned there is no main().
There is a UI loop that the OS runs that makes calls to methods you define or override in your program. These methods are likely called from/defined in onCreate(), onStart(), onResume(), onReStart(), onPause(), onStop(), or onDestroy(). All these methods may be overriden in your program.
The fundamental issue is that the OS is designed to run in a resource constrained environment. Your program needs to be prepared to be halted and even completely stopped whenever the OS needs more memory (this is a multitasking OS). In order to handle that your program needs to have some of all of the functions listed above.
The Activity lifecycle describes this best (your program is one or more Activities, think of an Activity as a screen).
Bottom line: Your program 'starts' at onCreate() through onResume() but the OS is running the loop. Your program provides callbacks to the OS to handle whatever the OS sends to it. If you put a long loop at any point in your program it will appear to freeze because the OS (specifically the UI thread) is unable to get a slice of time. Use a thread for long loops.
In Android environment, there is no main(). The OS relies on the manifest file to find out the entry point, an activity in most case, into your application.
You should read http://developer.android.com/guide/topics/fundamentals.html for more detail.
According to:
http://developer.android.com/guide/tutorials/hello-world.html
The application class must support a method for each activity that the Application
supports. In the general case, the onCreate is probably equivalent to the main/top
function for your needs.
Maybe it's possible by creating a timer and execute custom functions at every tick, reset the timer when it's at a specific time
The above answers provide a "why" as to there's no "main loop" on Android (which is important to understand). I'll offer a solution to the implied question, instead, as many visitors here will be looking for exactly that.
I believe the appropriate thing to do, here, would be to create an AsyncTask which operates as your "main loop". Or better yet, design your main loop to run as a java.util.concurrent future, which can be started and ended during lifecycle events (like rotation!), using signaling (keep your data separate). The AsyncTask API is deprecated, because it was complex, and handling it properly amounted to writing code that would, effectively, operate as an AsyncTask which cleaned up when the next problematic lifecycle event transpired.
Keep in mind that this will be a separate thread from the UI, and, as such, will be required to respond in short order to UI thread events, like "onPause" and "onDestroy". If your app does not respond within a certain period of time (~5 secs, iirc) to these events, or user input events, it will be killed by the OS. It's really prudent, for a real-time app, to be able to fully respond to these events in under 1 sec, even on the lowest-end device. You can use synchronization primitives to notify other threads that their response is pending, and they can use them to signal when they are finished (or simply end, in the case of a future).