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.
Related
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.
I want to know. What can be happen, when I use AsyncTask in IntentService.
Once onHandleIntent() returns, the service will be destroyed if there is no more outstanding work to be done. If the AsyncTask is still running, you will have leaked that thread. There is no guarantee that your process will remain running long enough for the AsyncTask to complete its work.
Since IntentService already gives you a background thread -- the one that onHandleIntent() runs on -- there is no need for another background thread. Just put your doInBackground() logic in onHandleIntent() of the IntentService.
Also, in general, using an AsyncTask from any service is unnecessary, as the service has no need to do anything on the main application thread.
You can use aynchronous task inside intent service and it will run perfectly.Since , intentService is to run the background task without Ui interaction but it is better for one work not to use asychronous task inside intentService.It will be helpful when You are using more than one long operations in the intentService otherwise that will struck the device
I think it is a completely bad idea to execute AsyncTask inside IntentService. I have an experience of AsyncTask inside JobIntentService which is different from IntentService but it causes crash. Just put codes inside doInBackground() in onHandleIntent().
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.
Is there any way on Android to know, if the thread running my code, is the UI Thread or not ? In swing there was SwingUtilities.isEventDispatchThread() to tell me if i am on the UI Thread, or not. Is there any function in the Android SDK that lets me know this ?
Answer borrowed from here: How to check if current thread is not main thread
Looper.myLooper() == Looper.getMainLooper()
Any Android app has only one UI thread, so you could somewhere in the Activity callback like onCreate() check and store its ID and later just compare that thread's ID to the stored one.
mMainThreadId = Thread.currentThread().getId();
Anyway, you can omit checking if you want to do something on the UI thread and have any reference to Activity by using
mActivity.runOnUiThread( new Runnable() {
#Override
public void run() {
...
}
});
which is guaranteed to run on current thread, if it's UI, or queued in UI thread.
Yes, there is a way.
Check the current thread object against main lopper's thread object. Main looper is always in the UI thread.
boolean isOnUiThread = Thread.currentThread() == Looper.getMainLooper().getThread();
Hum actually due to Android architecture, all Activities run in the main thread, ie the UI thread. So when you are coding an activity, everything that is in your Activity is in the UI thread.
That is why in Honeycomb an error have been added when you are making network calls in the main thread : it totally blocks the UI.
So by default you are in fact always working in the UI thread.
Another thing : unless you explicitely ask it to be in another thread, a Service will operate on the same thread as the activities of its application.
So, what to do ?
When you have to do heavy calculation in your activity; one solution is to use an AsyncTask (a class designed to allow you to easily use another thread). The code in onExecute() is run in another thread (but be cautious postExecute runs in your main thread). Another one is to manually start a new thread when AsyncTask is not really adapted.
If you create a service that does costly background tasks, make it run in another thread with the android:process=":my_process" attribute of the manifest. You will need to create an AIDL to communicate with this separated service, but it is not a complicated task.
Many objects, like for example the MediaPlayer, have Async variations of their methods. Try to to always use them.
Put a breakpoint where you want to check and, when it gets hit, check if you can interact with your UI (ie, if the UI is not frozen). If you can't interact with the UI then you are in the UI Thread, otherwise you are in a background thread.
I am getting data from the server using AsyncTask. I need to update the data periodically.
Whats the best way to do it?
You could use Timer class to schedule periodic task using TimerTask instead of AsyncTask
See :
http://developer.android.com/reference/java/util/Timer.html
http://developer.android.com/reference/java/util/TimerTask.html
And to update your UI you should follow this good tutorial :
http://android-developers.blogspot.com/2007/11/stitch-in-time.html
Set an alarm with AlarmManager and call your AsyncTask in your AlarmReceiver class.
You can do it either on your onProgressUpdate() or on onPostExecute() based on your requirement.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
http://developer.android.com/intl/de/reference/android/os/AsyncTask.html
Just to state one of the possibilities. You could also use ScheduledThreadPoolExecutor class. It has, generally, more possibilities then TimerTask.
To elaborate upon macarse's response, you can indeed "set an alarm with AlarmManager and call your AsyncTask in your AlarmReceiver class."
The concern I raised in the linked post still stands: I don't know if there are any life cycle issues associated with instantiating an AsyncTask from a WakefulBroadcastReceiver, i.e., I don't know if the above solution can lead to MyAsyncTask being killed prematurely.