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.
Related
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.
}
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
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 am confused on the following:
To use threads in a Java program, the simplest way is to extend Thread class and implement the runnable interface (or simply implement runnable).
To start the thread's execution. we must call the Thread's method start(), which in turn calls method run() of the thread. And so the thread starts.
The method start() (unless I am wrong) must be called exactly and only once for each thread. As a result, thread instances can not be reused unless somehow the run method itself runs in some-short of infinite loop that facilitates a custom implementation of the thread's reusage.
Now the javadoc
link text
says
Calls to execute will reuse previously constructed threads if available
I do not understand how this is implemented.
I provide in the execute method of the executor method my custom thread e.g.
ExecutorService myCachedPool = Executors.newCachedThreadPool();
myCachedPool.execute(new Runnable(){public void run(){
//do something time consuming
}});
How can this custom thread I delegeate to the executor framework be reused?
Is Executor is allowed to call method start() more than 1 time, while we can not in our programs?
Am I misunderstanding something?
Thank you.
Note that it's not Executor that calls start() - it's ExecutorService. And no, it's not calling start() twice. It doesn't start the task that you give it directly using Thread.start()... instead, it starts a thread which knows about that thread pool's queue of work. The thread will basically wait until there's some work to do, then pick it up and execute it, before going back to waiting. So although the thread performs several tasks, Thread.start() is only called once.
EDIT: Judging by the comments, you're a bit confused about the difference between a Runnable (which is a task to be executed) and a Thread (which is what executes tasks).
The same thread can execute multiple tasks. For a very simple example not using a thread pool, consider this:
public class MultiRunnable implements Runnable
{
private final List<Runnable> runnables;
public MultiRunnable(List<Runnable> runnables)
{
this.runnables = runnables;
}
public void run()
{
for (Runnable runnable : runnables)
{
runnable.run();
}
}
}
(Ignore the potential thread safety issues of using a List<T> from multiple threads.)
You could create a whole bunch of Runnable tasks capable of doing different things, then create a single MultiRunnable to run them in turn. Pass that instance of MultiRunnable into the Thread constructor, and then when you start the thread, it will execute each of the original runnable tasks. Does that help?
It is not calling start() more than once; instead the Thread in the pool never completes, but just stays alive---waiting. The source code is available for download if you want to look at it.
Each Thread in the thread pool can simply wait() for the Executor to hand it a new Runnable, but the Thread's own run() method has not completed. It simply waits for a new Runnable to be given to the Executor.
To "start" a thread more than once, create a runnable. For example:
//NO
private class T extends Thread { //not necessary to implement runnable
public void run(){
//...
}
}
void someMethod(){
T a = new T();
a.start();
a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO
}
Instead,
//Yes
private class T implements Runnable {
public void run(){
//...
}
}
void someMethod(){
T a = new T();
new Thread(a).start();
new Thread(a).start(); //YES YES YES
}
It is also possible to do this:
void someMethod(){
final Runnable r = new Runnable(){
public void run(){
//...
}
};
new Thread(r).start();
new Thread(r).start();
}
// r could also be a field of you class.
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();