This question already has answers here:
What is the different between Handler, Runnable, and Threads?
(6 answers)
Timertask or Handler
(3 answers)
handler or timer android
(3 answers)
Closed 4 years ago.
What is the difference between Android timer class and creating one with a Handler?
i tried both ways and i understand they can do different things but i dont know why,for example with android timer class i cant update views and i think that is a huge limitation,but with a handler the code feels messy.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//actions
}
}, 2000);
}
So,what is the best to do a action every tot seconds?
Edit:this isnt a duplicate because im asking about updating views with timers.
android.os.Handler is part of Android framework, the job will execute on the UI or main thread if you have created the Handler in the UI or main thread. Note that in Android you can only update views from the UI thread.
java.util.Timer on the other hand will execute on another thread so it cannot update the views.
So Handler is the recommended here. If you really want to use Timer you have to use runOnUiThread like:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//this will run on UI thread so you can update views here
}
});
}
}, 2000, 2000);
According to this answer : Android - Timertask or Handler , you're right about TimerTask class not being able to update views (cannot update the UI Thread).
Definitely opt for Handler. The syntax looks clean to be honest.
In my experience, Handler and the corresponding Android helper class HandlerThread are very flexible and allow you to do just about anything you need with regard to multithreading.
For example, running code on the UI-Thread:
Handler mUIHandler = new Handler(Looper.getMainLooper());
mUIHandler.post(new Runnable() {
/* Do something on UI-Thread */
});
Doing work on a background thread:
// This thread still needs to be explicitly started somewhere
HandlerThread mBackgroundThread = new HandlerThread("ThreadName");
// Sometimes you still need to think about some synchronization before calling getLooper()
Handler mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
// Execute code on the background thread the same way you would on the UI-Thread
Repeating a specific task after a given interval:
Runnable mTask = new Runnable() {
// Run this task (every 1000 ms) on the thread associated with mHandler
mHandler.postDelayed(this, 1000);
/* Perform the Task */
// You can also do this at the end if you wanted it to repeat 1000 ms AFTER
// this task finishes.
}
Related
Is there any way to call an activity from something that doesnt extend Activity? without running it on UI-tread. I want toast-messages in my game, like in candy crush. But I have no idea how to call the toast-activity in an efficient way during real-time.
I know you can use context and get activity from that but it does not run very smoothly. Does anyone have experience with how to do this?
Toasts as well as other components that manipulates the user interface must not be used outside of the UI thread.
What you could do in order to solve your issue, is to design a messaging system between the thread managing you game, and your UI thread. In order to do so, you can use a Handler and its messaging facilities (sendMessage, post, postDelayed ...) to send messages or even Runnables to be run on your main thread.
If you create a Handler in the main thread, it will automatically associate itself with your main thread's event loop, thus making every work sent to it be executed in the main thread.
A basic example of what you could do would be :
class MainActivity extends Activity {
// The handler is associated with your Activity's thread
private Handler _handler = new Handler();
// ...
private Thread _worker = new Thread() {
#Override
public void run() {
_handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Some text", Toast.LENGTH_SHORT).show();
}
});
}
};
};
As a shorthand, you could also use Activity.runOnUiThread(Runnable r) that executes the given runnable in the UI thread by default.
in my mainActivity, which is the sole activity of my application, I am creating the below handler and running a runnable inside it.
I have some misunderstandings about handlers and where they run.
See the code
Handler handler;
#Override
protected void onCreate(Bundle bundle)
{
handler = new Handler();
handler.postDelayed(r , 5000);
}
Runnable r = new Runnable()
{
#Override
public void run() {
FetchServerAndUpdateStatus(); //network stuff in here
handler.postDelayed(r , 5000);
}
}
I assume this code will still run in UI thread and I won't be able to make any network calls in there no ?
If yes, what shall I do ? Create and use a seperate thread ?
If I created a new thread, How can I run the postdelayed method ? The thread does not have post delayed ?
Does not using handler/runnable and using TimerTask and Runnable instead a better approach ? Or, just like the above handler/runnable, that will also run on the UI thread, unless created inside a seperate one.
When you construct a Handler it is bound to the thread it is constructed on.
onCreate() is run on the UI thread so this handler will be bound to the Looper on the main thread, and thus will run on that thread.
If you want a handler you can use on another thread you can construct one.
See the looper docs: https://developer.android.com/reference/android/os/Looper.html
Which has this block:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
synchronized (this) {
this.notifyAll();
}
Looper.loop();
}
}
Add this class and then in your onCreate do the following:
mLooperThread = new LooperThread();
mLooperThread.start();
synchronized (mLooperThread) {
while (null == mLooperThread.mHandler) {
mLooperThread.wait();
}
}
mLooperThread.mHandler.postDelayed(r , 5000);
This will cause the runnable to be run NOT on the UI thread, which is probably what you wanted.
For tasks that need to interact with the UI an AsyncTask may be better since it includes a mechanism to run things that touch Views when the task is done on the UI thread, since anything that touches a View must be done on the UI thread.
The other mechanisms for executing on the UI thread are to post to the view itself:
https://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)
or
[https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long)](https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long))
Or to ask the Activity to run it on the UI for you:
https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
It depends on what you do with your handler, you didn't show, how you want to obtain m_handler. If you create it with new Handler(Looper.getMainLooper()), it will run on UI thread.
If you want to run code in background (network operations) you should use AsyncTask
Basically this is what I am doing, instead of using a Timer I am using a Handler:
Handler h = new Handler();
Runnable r = new Runnable(){
public void run(){
//do something and schedule it again
h.postDelayed(r, 10000);
}
};
And I say h.removeCallBacks(r); when I want to stop it. Is it bad?
Is it bad.?
It's not bad, but that method just removes pending posts of Runnable.
Is it bad.?
No(unless you have some problems:)).
Don't forget to cancel that Runnable in the onPause method so you cancel any pending Runnable from running on a possible dead activity.
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.
Im running a Thread inside methode and i want to return a value once the thread finish, the problem that i tried to do join() but that blocks the UI thread.
How could i wait for the thread to finish and then return the value without blocking the UI thread ?
Boolean foo(){
myThread mt = new myThread();
mt.start();
return mt.isSentSuccessfully;
}
You can use Android's AsyncTask for that.
http://developer.android.com/reference/android/os/AsyncTask.html
When I use it, I put the background task in a class that extends AsyncTask and overwrite the onPreExecute() and onPostExecute(..) methods to show/hide the ProgressDialog. It works quite nicely.
If you really don't want to use the AsyncTask, then you might like to define a Handler
then in your background thread send a message to the main thread when the background job finishes with something like:
ActivityMainThreadClassName.this.myUpdateHandler.sendMessage(m);
where myUpdateHandler is the handler you created.
Did you try polling Thread.getState()?
Something like this:
android.os.Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run () {
if (thread.getState() == Thread.State.TERMINATED) {
// your code here
return;
}
h.postDelayed(this, 1000);
}, 1000);
This sample should poll a thread state every second... (I didn't tested it)
I need to perform a task repeatedly that affects both GUI-related and non GUI-related objects. One caveat is that no action should performed if the previous task had not completed when the next timer event is fired.
My initial thoughts are to use a SwingTimer in conjunction with a javax.swing.SwingWorker object. The general setup would look like this.
class
{
timer = new Timer(speed, this);
timer.start();
public void actionPerformed(ActionEvent e)
{
SwingWorker worker = new SwingWorker() {
#Override
public ImageIcon[] doInBackground() {
// potential long running task
}
#Override
public void done() {
// update GUI on event dispatch thread when complete
}
}
}
Some potential issues I see with this approach are:
1) Multiple SwingWorkers will be active if a worker has not completed before the next ActionEvent is fired by the timer.
2) A SwingWorker is only designed to be executed once, so holding a reference to the worker and reusing (is not?) a viable option.
Is there a better way to achieve this?
For (1), the scheduleAtFixedRate() method on ScheduledThreadPoolExecutor might be useful. From the javadocs:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
For (2), it looks like you could define a subclass of SwingWorker and construct new instances of the subclass for each iteration, instead of instantiating an anonymous subclass.
Have you looked at using a simple Java Timer, and a ReadWriteLock to determine if a task is running when the timer triggers again ? In this situation you could simply bail out of that particular iteration and wait for the next.
Why do you use a Timer? It would be simpler to keep the 'worker' running all the time, pausing via sleep() whenever the task took too little time to complete. You can still update things in the event dispatch thread using something like the following:
Thread background = new Thread(new Runnable() {
public void run() {
while ( ! stopRequested ) {
long start = System.currentTimeMillis();
// do task
long elapsed = start - System.currentTimeMillis();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// update UI
}
});
if (elapsed < tickTime) {
Thread.sleep(tickTime - elapsed);
}
}
}
}.start();