killing fragment or activity kill background threads? - java

I started doing some disk I/O in an asynctask within a fragment.
Does opening a new activity/fragment (on top of the previous fragment) kill the background thread? I think not for this action, but if I kill the fragment a different way or finish() an activity does it kill the background thread?
I am contemplating putting the I/O in a service with broadcast receivers but it may not be necessary depending on the answers here.

According to the official documentation :
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 pacakge such as Executor, ThreadPoolExecutor and FutureTask.
I am pretty sure the background thread isn't destroyed but is useless at that point. Say an activity started a Async task and updates the text of a button in postExecute. The problem is if the user does something unexpected like rotating his phone the activity is recreated and the context for the Async task is invalid. So it won't update the button text.
Have a look at the link below for better understanding and workarounds:
http://blogactivity.wordpress.com/2011/09/01/proper-use-of-asynctask/

Related

Thread Runnable vs AsyncTask Life Cycle

I would like to better understand what happens to a Thread or a AsyncTask when activity is destroyed.
So in this scenario, a Thread or AsyncTask would be started from activity, and user hits home button and onDestroy gets called triggering GC before either Thread of AsyncTask had a chance to finish.
Which one is more likely to run till completion in this scenario Thread/Runnable or an AsyncTask ?
Thanks.
Both will run
But the problem is if you have a reference to the killed activity on Thread of AsyncTask it will leak, and that is a problem you need to solve to make long running tasks synchronized with UI
If you've got a bigger task, I'd suggest you to spin up a Service, which are more easy to handle in Android context
AsyncTask based on thread so there is no huge difference in it's behaviour both will run after onDestroy. To avoid this behaviour you could use Loaders or manually stop execution of AsyncTasks/Threads in onDestroy method.

Android: How to stop Thread.sleep in an IntentService from the MainActivity

I am developing an Android App. I have a MainActivity class where I launch an IntentService.
In the IntentService class, I use Thread.sleep in the method onHandleIntent to handle a necessary pause.
Everything works fine.
What I would like to do is have a button in the MainActivity UI which can interrupt the Thread.sleep in the IntentService.
Is this possible? Thank you.
No, it's not possible. You cannot handle non UI related threads from the main UI thread. A thread is an independent entity when it's executed. If you want to be able to cancel a task that is already running, you should consider using AsyncTask and implement the doInBackground() method. Thereafter, it's possible to cancel this task from the UI if it's still executing.
Try to consider using a Service instead of the IntentService. The first one doesn't stop automatically, meaning it will listen to your commands you could send to it (I would go with EventBus) unless it is destroyed by the system to reclaim resources. Still you should definitely stop it on your own after you don't need it.
Anyways, I would better implement start/pause feature to control your flow rather than rely on thread interruptions.

What does the common advice "start a thread in a service" even mean?

Service callbacks run on the main thread just like activities' (unless otherwise specified). I seem to stumble upon lots of advice here on SO that goes something like "start a thread in a service [to do work in the background]". That doesn't make sense to me. What does it matter if I start a thread from activity code compared to service code, just as long as there exists a started service component in the application process?
If the answer is what I think (that it doesn't matter) then it's a shame that people give the impression that a service object needs to be somehow related to the background thread.
The term "background" can be misleading when it comes to Services as it can have two meanings. Services are used, simplistically talking, to run tasks even if there is no Activity of your application running. To clarify, think of a music player; you want the music to still play even if the Activity is not running. That is the definition of background that doesn't have to do with Threads; you are running a portion of your application in the background because you do not have any visible component of your app on the screen (maybe some Notification but no full screen UI).
Now, lets say you want to download some data from the internet. As you might know, you cannot perform long running tasks in the UI Thread (as of API 11+ you will get a NetworkOnMainThreadException), so you need to use a background Thread. Let's say you do not want to use an AsyncTask to download the content because a Service is better suited for your needs. In this case, you will have to start the Service on a background Thread. That is the second meaning of background, which basically means creating a new Thread. Android provides a class that does exactly this; IntentService. It is a Service that runs on a background Thread and that it finishes itself when the given task is done.
It does not matter where you actually start a thread if the lifetime of that thread is reflected via your app process state: http://developer.android.com/guide/components/processes-and-threads.html#Lifecycle
Android does not care if there is a Thread running or not. Threads just run even when your app is considered an empty process "that doesn't hold any active application components." Don't abuse that, since users don't want that apps are secretly active although they look dead.
If you want (and you should) that Android does not kill you randomly although your threads are not done you have to make sure that you keep e.g. a Service in started state.
Creating a thread from within a Service (or just using IntentService) will primarily result in better, simpler & cleaner code. For example because a Service has a Context and you can't leak your Activity from there. You also get free callbacks from the system.
And leaks via threads are extremely easy.
new Thread(new Runnable() {
#Override
public void run() {
SystemClock.sleep(Long.MAX_VALUE);
}
}).start();
Will leak your activity if you just put it in e.g. onCreate because the anonymous inner Runnable keeps a reference to your Activity and will not release it until the thread stops running and is itself garbage collected.
In case you really know what you are doing, feel free to start threads in Activities and sync their lifecycle manually to some empty Service. I would not recommend it because it's unlikely to be less work to do that correctly.

Service or Thread or AsyncTask

Pardon my questions, as I'm still very new to programming so I don't fully understand the concepts of mainthreads, and async tasks, and services, and threads. I'm reading the documentation about Services for Android because I want to perform some tasks off the main thread. It says:
If you need to perform work outside your main thread, but only while
the user is interacting with your application, then you should
probably instead create a new thread and not a service.
1.Are they saying that a "thread" stops immediately after you leave the app (i.e: Home button)?
For example, if you want to play some music, but only while your
activity is running, you might create a thread in onCreate(), start
running it in onStart(), then stop it in onStop(). Also consider using
AsyncTask or HandlerThread, instead of the traditional Thread class.
See the Processes and Threading document for more information about
threads.
2.If threads are baked into Java, why does android have AsyncTasks?
Remember that if you do use a service, it still runs in your
application's main thread by default, so you should still create a new
thread within the service if it performs intensive or blocking
operations.
3.Does this basically mean, that almost every service is basically going to have a thread created inside it?
4.Would it be bad to start an AsyncTask inside of a service?
1.Are they saying that a "thread" stops immediately after you leave the app (i.e: Home button)?
A Thread should be destroyed when the Thread that started it is destroyed. So, if you start a Thread in an Activity then it should be destroyed when that Activity is destroyed or transferred to a Service. For instance, you can start music in a Thread and update the songs there but if you want it to keep playing when the Activity is destroyed then it should be moved to a Service
2.If threads are baked into Java, why does android have AsyncTasks?
An AsyncTask allows you to perform background work and easily update the UI before, during, and after the background work is done by utilizing any of its built-in methods except for doInBackground() because it is the only one that doesn't run on the UI Thread
3.Does this basically mean, that almost every service is basically going to have a thread created inside it?
Not necessarily but you could create a Thread inside of it
4.Would it be bad to start an AsyncTask inside of a service?
No. You could do this.
AsyncTask is a great way to do background work. Its methods make it very easy to update the UI. But you need to read through the documentation carefully (maybe even a few times) to make sure you completely understand how to use them. Also, remember that these are for short-lived operations so they can be good for downloading network data but shouldn't be used for things that last more than a few seconds (According to the docs)
A thread doesn't stop immediately when you leave the app. The suggestion to use a separate thread is only so you don't block your app's GUI.
AsyncTasks actually use a ThreadPool behind the scenes as creating a thread is an expensive process. If you have many short lived tasks, using AsyncTask is just a quick, easy, but efficient way to execute them without blocking your application's GUI.
Yes, essentially. A service is more heavy weight than a thread though. Using a service in place of a thread is not a good idea. Also services can actually be made to execute on a whole other process. Just FYI.
No. It would be a good idea, if you've many short lived tasks to execute.
If you are only trying to execute tasks off the main thread, you don't need a service. Just create another thread.
AsyncTask behind the scenes just submits your task to a thread pool for execution. If you have many short lived tasks, like parsing networking traffic, AsyncTask is great.
However, if you are handling a huge amount of requests, you might want more control over the thread pool executing your tasks.
No
Because a main thread controls the UI while asynctasks can make heavier tasks while keeping the UI lag-free.
No, but if you want your service to make heavy lifting like loading stuff from internet then it should use an asynctask. Most services are used to load data from internet so most of them have asynctasks. Note that for the service to be kept alive after the activity dies, you must specify it. Services by default die along with the activity unless configured properly
No
You might be confusing by thread and task and process.Task is small kind of process.An process
is a pro-gramme that running in your system example when start your task-manager it is showing all the process running like Internet-explorer but thread is small lightweight process means you can say sub-process that in execution for performing some task but asynchronous in android is just similar to thread but it may-be long.Take a example in android you are playing temple-run in android-phone ,and some-one is calling you so that high priority task will performed and current thread is paused there and so many method are there
like onCreate() ,onPause(),you can understand it.

Background HTTP tasks

I have a splash page on my app, and what I want to do is initiate a background task to start downloading things so they're ready when the user needs them.
So for example a picture of the week or something.
Splash screen starts (start background task)
Splash screen finishes (background task still working)
Home screen starts (temporary "loading" place holder)
User navigates to another activity
Download finishes
User returns to home screen which is updated with picture of the week
Now I'm aware of Async Tasks, but I've heard that async tasks get canceled on finish() and I've also heard they don't get canceled.
Is this sort of task, background loading best handled in a service?
Can anyone provide me with a tutorial on loading things like this in the background?
EDIT:
People are mentioning that UI work should be in the UI and non-UI in the non-UI. I've considered handlers, but does the listener work when the current activity isn't active?
Lets say I start a handler in the main and then switch pages. When I come back I'm pretty sure the main UI won't be updated because the listener didn't trigger while I was viewing another page.
I'm assuming I'll have to create a class just for storing variables or something. Once the service finishes, it'll set a "pic_of_week_loaded" to true and when the main reloads it checks this var. How would I go about this?
You can extend from Application class, create a thread (or AsyncTask) within it that will basically download stuff from Internet. After it finishes, you can notify the home screen activity to show up the contents into the place holder.
Another choice is to use the Android Asynchronous Http Client
I would just do it in the activity but make sure to check that the activity is still active when you go to display it (make sure onDestroy hasn't been called on it yet)..
Then I would cache the result so you don't have to load it again from the web (store the date in the filename so you know which date the picture is for so you know if the cache holds the latest one already).
Consider using IntentService to do your background job, so you will not be bond to activity life cycle.
EDIT: as per comments.
Using own application object is quite simply. Just create it like this:
final public class MyApplication extends Application {
....
}
then update your Manifest to look like this:
<application
android:name=".MyApplication"
...
and theoretically that's it. You can now add your own methods there, incl. async task operations. And you can get handle to your application object with just MyApplication app = (MyApplication)getApplicationContext(); and then do app.XXX(); Some important notes though: if you'd like to use AsyncTask in your ApplicationObject, be aware of Android Bug #20915. The workaround, as per discussin there is to do this in onCreate():
public void onCreate() {
// Workaround for android bug #20915
// http://code.google.com/p/android/issues/detail?id=20915
try {
Class.forName("android.os.AsyncTask");
} catch (Exception e) {
e.printStackTrace();
}
super.onCreate();
...
I will try to explain why (1) keeping global state in Application sublcass and (2) using AsyncTask are both bad approaches for this case.
(1) OS may kill your app process if the app is not in the foreground and there is no running services in the app at the moment. More details on this in this post: How to declare global variables in Android?
(2) AsyncTask is tricker than it looks at first. :) For instance, if ((OS < 1.6) || (OS >= 3.0)) all tasks are run on the same background worker thread by default. I mean ALL tasks for the current Java process are executed on the only background thread. So the next possibly started tasks in other activities will have to wait untill that first/init one is done. I think this is not what you'd like to get (if user navigates from Home activity to some other activity and that another activity will need to load some data using AsyncTask, then make sure your first/init task is done quickly, because it will block any subsequent tasks). Of course, if the amount of work for the first/init task is not big, then you can don't worry about this point. More details on how AsyncTask works in this post: Running multiple AsyncTasks at the same time -- not possible?
So my advice would be to use IntentService to download the image/date you need on startup. Once it downloads the data it sets the flag in SharedPreferences and sends a broadcast. By this time the Home activity may be in 3 states:
active (passed onResume(), but not yet onPause())
paused (passed onPause(), but not yet returned to onResume)
destroyed
While it is active it uses broadcast receiver to listen to the service. When it is paused it unregisters the broadcast receiver, but when it comes to active the first thing it does is to check the flag from SharedPreferences. If flag is still not set, then registers broadcast receiver.
1. Well AsyncTask was introduced into android to give what its know for Painless Threading, but i don't think thats the case here....
2. Now Its always good to keep the UI work on the UI thread, and Non-UI work on the Non-UI thread, and that became a rule from the arrival of HoneyComb version of Android.
3. Now as you want to download few things at background, which DOES NOT INCLUDE reflecting the output on the UI. Then i think you look into CountDownLatch Class in the java.util.concurrent.
4. Else you can always run a Non-UI thread at background.
I prefer to use Threads and Handlers for background tasks. The thread will execute some operation in the background, then when the task is complete, update the handler to update the UI. Here is some sample code below:
Handler handler = new Handler() { //Declare this as a global variable to the class
#Override
public void handleMessage(Message msg) {
//display each item in a single line
if(msg.obj.equals("update subcat")){
subcategoryAdapter.notifyDataSetChanged();
}else if (msg.obj.equals("update products")){
productsAdapter.notifyDataSetChanged();
}else if (msg.obj.equals("update cat")){
categoryAdapter.notifyDataSetChanged();
}
}
};
Here is your background task:
Thread background = new Thread(new Runnable() {
#Override
public void run() {
getSubCategories(((Categories)searchResults.get(pos)).ID);
handler.sendMessage(handler.obtainMessage(pos, "update subcat"));
}
});
background.start();

Categories