I have a gui thread starting a new thread to do some busy things. The GUI thread will wait the worker thread to be completed, in the mean time the GUI need to be responsive.
Psedo code:
main thread:
start_thread();
wait_thread_done();
work thread:
doing_sth();
notify_main_thread();
What is the easiest way to do this in android?
The easiest way to do this is with Android's AsyncTask. The documentation is here
http://developer.android.com/reference/android/os/AsyncTask.html
And you can call Activity.runOnUiThread() to update the UI from your background task.
A small working snippet :
new Thread() {
public void run() {
handler.post(new Runnable() {
public void run() {
try{
// **Do the GUI work here**
} catch (Exception e) { }
}});
};
}.start();
Call Activity#runOnUiThread(Runnable), the Runnable you pass to that method will execute on the GUI thread.
Or use an AsyncTask - which is the proper way to do it.
waiting for result will make gui thread unresponsive. you need to use AsyncTask and override onPostExecute to perform operation required when background thread is done
Related
Whenever this code is executed the application crashes, but when a handler is used the application works as expected.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
//this code needs to be inside a Handler ??
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
//this code needs to be inside a Handler ??
}
};
Thread thread = new Thread(r);
thread.start();
}
Here all the answer have mentioned use of handler is used in Android with UI thread. But Let me add more to it.
If you have gone Android documentation/tutorial you would know that
When an application component starts and the application does not have
any other components running, the Android system starts a new Linux
process for the application with a single thread of execution. By
default, all components of the same application run in the same
process and thread (called the "main" thread or uiThread).
for more info refer
Now coming to your mentioned example; you have created another thread using Runnable...so there might be scenario you need thread(s) other then just mainThread in Android Application.
If you are good in JAVA Threading concept then you would know how Interthread communication happens and for different ways how it can be done refer
So coming back to question in android we have mainThread or uiThread so called which holds our ui i.e. view component. These component are private to mainThread so other thread cannot access it...which has been mentioned in previous answer. This is where Handler comes into picture you do not need to worry how your message would be passed from one thread to another.
Handler
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your
own.When posting or sending to a Handler, you can either allow the
item to be processed as soon as the message queue is ready to do so,
or specify a delay before it gets processed or absolute time for it to
be processed. The latter two allow you to implement timeouts, ticks,
and other timing-based behavior.
For more info refer docs AND
For more info with handler and UI thread
Code that deals with the UI should be run on the UI (main) thread.
You (probably) create a handler on the UI thread, so all messages sent via it will run on that thread too.
The Runnable is use for background process(background thread) and textview is in your UI thread so background thread can't communicate with foreground thread so it will gives you error and crashes your application.you can also use the runOnUiThread. example.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
try {
// code runs in a thread
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
};
Thread thread = new Thread(r);
thread.start();
The reason why your app crashes is that you modify View from a non-UI thread.
If you do it using a Handler that belongs to UI-thread this works as expected.Update
If you need to run Runnable to modify UI you may choose from:
1) yourActivity.runOnUiThread(Runnable r)
2) yourHandlerOnUIThread.post(Runnable r)
3) yourView.post(Runnable r)
I created an asynctask and in its doInBackground() method i started a thread like this:
private class myAsyntask extends Asynctask{
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run()
{
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
}
onPostExecute(){
//do something related to that variable
}
}
problem I am facing is after 1st iteration of Thread.sleep() , onPostExecute() is called , instead I thought that asynctask will run this thread on background and when that boolean is true onPostexecute() is called.I am not able to understand why this happens ?
AsyncTask automatically creates a new Thread for you, so everything you do in doInBackground() is on another thread.
What you are doing is this:
AsyncTask creates a new Thread and runs doInBackground().
a new Thread (t) is created from the AsyncTask-Thread.
doInBackground() is completed, as all it does is create the Thread t and thus jumps to onPostExecute().
Thread t would still be running in the background (however, you do not call start() on t, meaning that it is not started).
Instead you want your doInBackground() method to look something like this:
doInBackground(){
while(someBoolean!=true){
//Perform some repeating action.
Thread.sleep(100);
}
}
First of all, in your code you don't even start thread t, so all that happens in doInBackground is creation of new thread and then moving on to onPostExecute().
Secondly, you don't even need separate thread, since doInBackground() handles this for you, so you can just use something like
doInBackground(){
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
if you wish, however, to stick with separate thread, you can start thread and wait for it's completion by using .join(); like
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run() {
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
t.start();
t.join();
}
onPostExecute can only be called when doInBackground has return-ed. In your code, the only possible way this can happen is sleep throwing an Exception (InterruptedException??)
I am developing an application using Android SDK. In this application I am facing a problem when an Activity starts a Thread. The new Thread starts an AsyncTask, but the Thread has to wait for completion of the AsyncTask execution.
Is it possible to start AsyncTask in a thread, and if so, how should it be implement?
Please can anyone share your experience with me about this kind of tasks.
Thanks in advance
You should not create an AsyncTask from a thread other than main thread.
If you should wait anyway, why create AsyncTask? perform it on the thread.
just say thread to sleep for some times and then check a variable again like this
in below code someValue was setted in asynctask postExecute method
new Thread(new Runnable(){
#Override
public void run(){
while(!someValue) {
try {
Thread.sleep(200);
} catch {
Log.i("LOG", "ERROR");
}
}
Log.i("LOG", "Async Task Finished");
}
}).start();
Coming from the basic Java world I know there's a way to spawn a thread by creating a new Runnable and passing it to a new Thread and calling start on it. Something like:
Runnable r = new Runnable() {
#Override
public void run(){
}
}
new Thread( r ).start()
Now joining the Android world it seems the Android eco system provides a few other ways to spawn a thread. One of them is Activity.runOnUiThread (for having stuff done on the UI) and Handler.post( runnable ).
What I am wondering about is what's the Android preferable way of spawning a new thread. I do see a lot cases such as:
Handler handler = new Handler()
handler.post( r )
Is there a good reason to use Handler to spawn a thread as opposed to creating a new Thread old way?
Thanks.
Yev
Check out the AysncTask framework. It seems like that's how Google wants you to handle threads...although you can use standard java threading.
The Handler in the way you've demonstrated doesn't actually spawn a new thread. Handlers are not threads, but are rather a means of IPC to let one thread tell another thread to run code. You still spawn off threads in the same old way, but the Handler helps those threads communicate better.
Say, for example, you have a Thread that you've spawned off in the background in the usual way:
Runnable r = new Runnable() {
#Override
public void run(){
}
}
new Thread( r ).start()
It runs in the background doing processing, but it needs to update the UI with it's progress, so it calls back to the Activity:
onProgress(int progress) {
// update UI
}
If you run that code as is, it will throw an exception, because only the UI thread is allowed to update the UI. Handlers can solve that problem like so:
public void onProgress(int results) {
mHandler.post(new UIUpdater(results));
}
private class UIUpdater implements Runnable {
UIUpdater(int results) {
//construct whatever...
}
#Override
public void run() {
//Update UI
}
}
Alternately, you can have Android manage Threads and Handlers for you through the AsyncTask framework
Handler is not supposed to spawn thread , but to post new task to UI thread. IMO the way to spawn thread is the java way, through runnable or extended thread directly. The android guys wrapped an Executor around the Async task and exposed some method that run directly in UI thread, and one to run your task in background.
At a certain point of my AsyncTask, after some validations have been done, I need to spawn off another thread to do some other work. So I'd like two background threads at this point, each doing it's own thing (approx 2-3 seconds to execute each). The idea is to maximize performance on dual core processors like Atrix.
Is it acceptable to create another asynctask & execute it from the first one? Can anyone suggest a better way of doing this?
Thanks!
EDIT: I'm wondering what publishProgress() from the second task would even do... since it was not started from an Activity?
Is it acceptable to create another
asynctask & execute it from the first
one?
Yes, but only inside onProgressUpdate() or onPostExecute() since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.
I'm wondering what publishProgress()
from the second task would even do...
since it was not started from an
Activity?
It does exactly the same thing, since you are starting it from the UI thread.
If you are looking for a mechanism of executing multiple async tasks, from 3.0 and above it supports a method called executeOnExecutor which will allow you to schedule tasks in parallel on a pool of thread managed by Async Task.
An AsyncTask is useful for doing some background work while communicating with the main thread to handle UI changes. It appears that this is not your case.
Besides, an AsyncTask must be executed from the main thread. From the AsyncTask reference:
There are a few threading rules that
must be followed for this class to
work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
You can a take a look at this article and see what fits you best.
This can be done using message passing concurrency and a single handler. Proof of concept code follows:
private Handler myHandler= new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
Toast.makeText(Main.this,"Message0", Toast.LENGTH_SHORT).show();
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(3000);
}
catch(Exception e){}
myHandler.sendEmptyMessage(2);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
break;
case 1:
Toast.makeText(Main.this,"Message1", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(Main.this,"Message2", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
break;
}
}
};
I launched the first thread on a button click as in:
ON CLICK HANDLER
threadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(1000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(0);
try {
Thread.sleep(3000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(1);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
}
});
The calls to thread sleep is to mimic a time intensive task.