When trying to learn how to create a delay I researched and found the dominant answer to be to use Handler/Runnable/postDelayed.
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
delayedMethod();
}
};
handler.postDelayed(r, 1000);
That worked ok for a while, but I've added a few more things going on and now they are sometimes happening in the wrong order.
This set of events:
paintScreen1()
...
delayedPaintScreen2()
...
paintScreen3()
is screwing up (sometimes) and doing this:
paintScreen1()
...
paintScreen3()
...
delayedPaintScreen2() (runs last and gets messed up by the actions of paintScreen3)
There doesn't seem to be another good way to create delays - one that doesn't create threads.
Solutions I have tried in order to make sure the code events run in the proper order:
0 Putting the main process inside one big synchronized block.
1 Putting the synchronized keyword in the method name of every method involved in the main process.
2 Putting the synchronized keyword only on the method in the Runnable.
3 Taking away the Handler/Runnable/postdelayed and replacing with handler.sendEmptyMessageDelayed(0,1000)
4 Making one Handler instance variable, used by every Handler/Runnable block (as opposed to Handler handler1, handler2, handler3, etc.)
5
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
waitOver = true;
}
};
handler.postDelayed(r, 1000);
while (waitOver == false) {
}
delayedMethod();
waitOver = false;
My next attempt may be to try to used the Thread class somehow so I can call thread.join().
When that fails the next thing will be very long and complicated, I fear.
Any suggestions?
Any simple examples of a solution?
Thanks
Edit: I may be confused about whether Handler/Runnable results in literal threading or not.
Edit: It's a game. User makes a move, screen updated to show the move, calculation tells that they scored a point, recolor the boxes on the screen, add delay to allow user to see their point, then call method to removed colored squares, when that method completes and we return to the method that called it (containing the Handler/runnable), the code continues down to a point where it calls another method that results in a random square of the board being turned purple. So it should happen user-move, repaint to show point scored, delay so user can see point scored, repaint to erases squares, then random purple square happens. Sometimes what will happen (as far as I can tell) is the random purple square will execute before it should, choose one of the squares where the point was scored, interfere, and make it so the cleanup method gets confused and fails to cleanup.
mainmethod() {
...
if (pointscored) {
squaresglow();
...
//delay so user can see the glow before the cleanup happens
Handler-runnable
cleanup();
postdelayed
}
...
purpleSquare();
}
I hope this is not even more confusing. purpleSquare runs before cleanup and things get screwed up.
Edit:
Tried this:
6
CountDownLatch doneSignal = new CountDownLatch(1);
Handler handler=new Handler();
final LatchedRunnable lr = new LatchedRunnable(doneSignal);
handler.postDelayed(lr, COMPUTER_MOVE_DELAY);
try {
doneSignal.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
class LatchedRunnable implements Runnable {
private final CountDownLatch doneSignal;
LatchedRunnable(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
public void run() {
delayedProcess();
doneSignal.countDown();
}
}
7
ExecutorService executorService = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(1);
executorService.execute(new Runnable() {
public void run() {
try {
Looper.prepare();
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
delayedMethodCleanupCalc();
}
};
handler.postDelayed(r, 4000);
} finally {
latch.countDown();
}
}
});
try {
latch.await();
delayedMethodPaintScreen();
} catch (InterruptedException e) {
// todo >> handle exception
}
purpleSquare runs before cleanup and things get screwed up
mainmethod() {
...
if (pointscored) {
squaresglow();
...
//delay so user can see the glow before the cleanup happens
Handler-runnable
cleanup();
postdelayed
}
...
purpleSquare();
}
You have a design flaw here. Think of Handlers as a queue of messages that will execute code "later" whenever the processor decides to process messages and postDelayed as an inexact way to stuff that message at the bottom of the queue. If you call postDelayed and you still have lines of code left in the current method to execute, chances are very good that those lines will execute before postDelayed messages are even received.
What you are trying to do is to make sure purpleSquare() gets called after the pointscored routine has done it's job, which may require waiting for it to finish. PostDelaying to the message queue is not what you should be doing in this case. What you should be using is a semaphore and a pointScored thread.
Consider the following code design:
final Runnable pointScoredTask = new Runnable() {
public synchronized void run() {
try {
squaresglow();
//...
Thread.sleep(2500); //2.5 sec before cleanup occurs
cleanup();
} catch (InterruptedException e) {
}
notify(); //make sure we call notify even if interrupted
}
};
void mainmethod() {
//...
if (bPointWasScored) {
synchronized (pointScoredTask) {
try {
Thread psThread = new Thread(pointScoredTask,"pointscored");
psThread.start(); //thread will start to call run(), but we get control back to avoid race condition
pointScoredTask.wait(6000); //wait no more than 6 sec for the notify() call
} catch (InterruptedException e) {
}
}
//if a point was scored, nothing past this line will execute until scoreglow has been cleaned up
}
//...
purpleSquare();
//...
}
I know you'd rather avoid threads, but there are some things that just work much better when you use them. Try the above design and see if that works out the synchronization issues you were seeing.
Related
So I have this method called PredictionEngine(int) that I want to run a certain number of time with a certain time-delay between each run. The method goes like this:
private void PredictionEngine(int delay) throws Exception {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
enableStrictMode();
String val = null;
try {
if (tHighPass == 0 && tLowPass == 0 && tKalman == 1) {
//Magic
} else {
//Magic
}
} catch (Exception e) {
e.printStackTrace();
}
enableStrictMode();
new DropboxTask(side_output, "Result", val).execute();
}
}, delay);
}
As obvious, I am running a network operation in the main thread as this is a research app and no client is ever going to use it.
I want this whole function to run for say a 100 times with a certain delay, say 2 seconds. The initial thought was to do this:
for(loop 100 times){
PredictionEngine(int)
Thread.sleep(2000); //sorry for StackOverflow programming.
}
However I don't want to block the main thread as I am reading some sensor data there. Any ideas for the same would be very helpful!
Thanks.
The best way to solve this is by using rxJava library, because it allow to create, modify and consume streams of events. You can implement everything in a few lines of code and modify it so operatioin will be performed in background as well.
Observable.interval(1, TimeUnit.SECONDS)
.take(100)
// switch execution into main thread
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(t -> {
doSomethingOnMainThread();
});
On the other hand, there is another solution- you can use Handler, which is usually bein used for thread communication. It has method .postDelayed() allowing you to postpone execution of task. Handler can be conveniently used along with HandlerThread. But, rxJava is more convenient and simple way to solve your problem.
While creating your Handler, you can provide a looper as one of the constructors parameters that is based on different thread then the main thread:
HandlerThread thread = new HandlerThread("Thread name", android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Looper looper = thread.getLooper();
Handler handler = new MyHandler(looper);
Messages received by MyHandler will be processed on a separated thread, leaving the UI thread clear from interferences.
To loop on the task periodically, use something like:
for (int i=0; i<100; i++){
handler.postDelayed(new Runnable(){
...
...
...
}, i*delay);
}
This way, in case you decide that the periodic tasks need to be canceled, you will always be able to invoke:
handler.removeCallbacksAndMessages(null);
I tried to solve the issue as follows without blocking the main Thread
I created the worker thread for looping and still running the predictionEngine() on main thread
MyThread t = new MyThread(2000, 3000); // delay and sleep
t.startExecution();
Worker thread class looks as follows
class MyThread extends Thread{
private int delay;
long sleep;
MyThread(int delay, long sleep){
this.delay = delay;
this.sleep = sleep;
}
#Override
public void run() {
for(int i = 0; i < 100; i++){
try {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
predictEngine(delay);
}
});
Log.i("Mtali","About to pause loop before next predict");
sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void startExecution(){
start();
}
}
Hop this helps!
I use the code below for getting some work done everytime after some time interval, and using post delay in 'finally' clause and oustide of runnable. Here is the code.
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
// do somthing
} catch (Exception e) {
// TODO: handle exception
} finally {
handler.postDelayed(this, 60000);
}
}
};
handler.postDelayed(runnable, 60000);
handler.postDelayed(runnable, 60000); will run two times or a single time.
it depends!
first matter
how the each try / catch / finally block completes normally or abruptly?
the finally block "always ^" executes when the try block exits
This ensures that the finally block is executed even if an unexpected exception occurs.
^ exception from above - finally may not be executed if jvm exits or thread gets killed
for details see java specs:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2
second matter
how Handler post/postDelayed method executes will pass? or fails? for some reason - for second this may happen if message was not placed in to the message queue - on failure, usually because the looper processing the message queue is exiting.
but most likely your statement will make a INFINITE loop
** ps. you need to throw an exception in try block or remove catch block (as try{} finally{} ) can exist "without" catch but code in catch block without rising any exception will make a compiler complain (code will not compile)
if you want loop n-times+1 you need to add some condition before postDelayed in Runnable run() method
in your case code flow execution:
postDelayed method from last line outside definition of runnable
execution of runnable by:
start of try block
with or without passing catch
through finally block with postDelayed in runnable run() method - wich will place runnable in message que for delayed execution on main thread
then infinite loop on 2
so should i remove last postDelay out side of run() method to achieve postDelay run only ones in one loop. – AndroidMob
you can write this in such way:
final Handler handler = new Handler();
handler.post(new Runnable() {
// this int will also be passed to method post delayed
// as "this" keyword applies to Anonymous Class
// which body contains everything between brackets of new Runnable() { ... }
int withThis = 1;
#Override
public void run() {
handler.postDelayed(this,1000);
}
});
so where should i call method to get done somthing ? in run() method..? – AndroidMob
this also depends what you want to achieve:
example
handler.post(new Runnable() {
int counter = 0;
#Override
public void run() {
boolean wasPlacedInQue = false;
doPreMethod();
if(counter =< 10) {
doMethod();
wasPlacedInQue = handler.postDelayed(this,1000);
}
if(wasPlacedInQue) {
counter++;
doPostyMethod();
} else doFailureMethod();
}
the code in run() method is executed synchronously on so called UI Thread - i'ts main thread which executes your application see:
https://developer.android.com/training/multiple-threads/communicate-ui.html
if you are interested to study it more I have made a full working example for you:
https://gist.github.com/c3ph3us/7d237d540e60597369856cb1fa652a23
it surely will run two times. Because they are two different messages and handler will handle them separately.
I have a simple Activity with two buttons "On" and "Off". I want start changing color of background in cycle with button "On" and stop this with button "Off". Also I need to have red color by click on "Off" button. I have wrote simple programm and everything is fine, but I can't understand one thing. Why the last color not always red? If I use code in main threads cycle
Thread.sleep(100);
or
Thread.sleep(1000);
I always have red color, but if I set
Thread.sleep(10);
I have random last color. Why??
Thank you !!
I have this code:
public class MyActivity extends Activity {
final Handler myHandler = new Handler();
private int randColor;
final Runnable updateColor = new Runnable() {
public void run() {
final Random random = new Random();
randColor = Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255));
mRelativeLayout.setBackgroundColor(randColor);
}
};
private ColorChanger myThread;
class ColorChanger extends Thread {
private volatile boolean mIsStopped = false;
#Override
public void run() {
super.run();
do
{
if (!Thread.interrupted()) {
myHandler.post(updateColor);
}
else
{
return;
}
try{
Thread.sleep(100);
}catch(InterruptedException e){
return;
}
}
while(true);
}
public void stopThis() {
this.interrupt();
}
}
private RelativeLayout mRelativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
}
public void onflagClick(View view) {
myThread = new ColorChanger();
myThread.start();
}
public void onflagoffClick(View view) throws InterruptedException {
myThread.interrupt();
if(myThread.isAlive())
{
try {
myThread.join();
} catch(InterruptedException e){
}
}
else
{
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
}
I agree with the previous answer-ers, but propose a different solution.
First let me say that I recommend you stop using Runnables. In general posting a Runnable to a Handler is less efficient then sending a Message, although there are very rare exceptions to this rule.
Now, if we send Messages, what should we do? What we basically want to do is keep doing whatever we're doing until a condition is hit. A great way to do this is to write a Message Handler that receives a Message, does our work (setting the color), checks if we should keep going, and if so schedules a new Message in the future to do more work. Let's see how we might do this.
Assume the code below is inside an Activity.
private static final int MSG_UPDATE_COLOR = 1;
private static final int DELAY = 10; //10 millis
private final Object mLock = new Object();
private boolean mContinue = true;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_COLOR:
synchronized (mLock) {
if (mContinue) {
setColor(Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255)));
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_COLOR, DELAY);
} else {
setColor(Color.RED);
}
}
break;
}
}
}
}
public void onflagClick(View view) {
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
public void onflagoffClick(View view) throws InterruptedException {
synchronized (mLock) {
mContinue = false;
}
// cancel any pending update
mHandler.removeMessages(MSG_UPDATE_COLOR);
// schedule an immediate update
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
Okay, so, what is happening here. We've created a Handler that will do all the color updates. We kick that off when our start event happens. Then the Message schedules a new message (and therefore color update) in ten milliseconds. When the stop event happens we reset a flag that the message handler reads to determine if a new update should be scheduled. We then unschedule all update messages because it might be scheduled for several milliseconds in the future and instead send an immediate message that does the final color update.
For bonus points we eliminate the use of a second thread which saves resources. Looking carefully I've used synchronized blocks, but these are actually unnecessary because everything is happening on the main thread. I included these just in case someone was changing mContinue from a background thread. Another great point of this strategy is that all color updates happen in one place in the code so it is easier to understand.
When you post to Handler, it will run your Runnable at some given time in the future. It is not immediate. It also works in a queue so the more times you post to Handler you are going to stack up the commands that will all get executed in order eventually.
You're facing a race condition because with Thread.sleep(10), the program is most likely stacking up a lot of Runnables to execute. They will run regardless of whether or not your Thread is running because they've been queued up to run on the main thread. Thread.sleep(100) or Thread.sleep(1000) doesn't have this issue simply because you're giving the system enough time to execute all color commands. However, it is still possible to have this issue if you pressed the off button at just the right time.
As DeeV told you, Handler sends Runnables to a Looper that is basically a Thread looping inside processing messages or runnables in each loop. You are queuing messaged to the main Looper and then you are sleeping your worker Thread. Its possible that you are sending for example 2 runnables in a row between each loop of your worker thread, but the main looper has only executed the last one so you cannot see each color as you want.
If you want a simple solution to make it work, you can use an Object or a CountDownLatch to synchronize your main Looperwith your worker Thread.
For example: Just before you will sleep your worker Thread you can do the next thing myLockObject.wait()
Then, you should change post(Runnable) to sendMessage(Message). In handleMessage from your Handler you can do myLockObject.notify() (Keep in mind that handleMessage will be executed inside the Looper that you have created your Handler or you can specify any Looper you want explicity). To obtain a new Message you should use myHandler.obtainMessage().
This will make your worker Thread wait your main Looperto process your runnable just before you wait X time until you post next color. Obviously you should create your new Object as a field of your Activity for example:
private myLockObject = new Object()
I finally got my app working, i just have one issue which i would like to correct.
I have a button which controls a thread that runs a couple function in the background. The functions in the background eventually stop the thread whenever a certain value is reached. What i am having issues doing is pressing that same button again to just stop the thread manually. Currently I can only start the thread and wait for itself to finish. I am able to do other things in the app, so the thread is running on its own, i just want to kill it manually.
public void onMonitorClick(final View view){
if (isBLEEnabled()) {
if (!isDeviceConnected()) {
// do nothing
} else if (monitorvis == 0) {
showMonitor();
DebugLogger.v(TAG, "show monitor");
//monitorStop = 4;
Kill.runThread(); // I want a function here that would kill the
// thread below, or is there something that
// can be modified in runThread()?
// I did try Thread.Iteruppted() without luck
shutdownExecutor();
} else if (monitorvis == 1) {
hideMonitor();
DebugLogger.v(TAG, "hide monitor");
monitorStop = 0;
runThread(); //The running thread that works great on its own
}
}
else {
showBLEDialog();
}
}
private void runThread() {
new Thread() {
int i;
public void run() {
while (monitorStop != 3) { //This is where the thread stops itself
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
((ProximityService.ProximityBinder) getService()).getRssi();
rssilevel = ((ProximityService.ProximityBinder) getService()).getRssiValue();
mRSSI.setText(String.valueOf(rssilevel) + "dB");
detectRange(rssilevel);
}
});
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
On first look, you could simply set monitorStop = 3, which would cause the thread to eventually stop after it's timeout completes.
The problem with this, is that I presume if you push the button again or your code modifies monitorStop at some point in the future, then the thead you wanted dead, might stay alive. ie: monitorStop will need to stay equal to three for at least 750ms to assure the thread will comlete it's loop and die.
The correct way to do this would be to create your thread as a new class with it's own monitorStop parameter. When you create the thread, you would keep a reference to it and modify the thread's monitorStop parameter. This way the thread would finish without interruption. If you wanted to create a new thread, then this would not affect the old thread from finishing appropriately.
I am building an android board game which features AI. The AI gets a turn and has to invoke a series of actions after which it posts invalidate to my custom view to update.
I need to slow down these actions so the user gets to see the AI having its turn rather than it flashing by.
I have tried something along these lines
try {
doFirstThing();
Thread.sleep(500)
//post invalidate
doNextThing();
Thread.sleep(1000)
//post invalidate
}
catch (Exception e) {
}
However this is having absolutely no effect. Also this is running in a separate thread if this wasn't obvious.
Whats my best option I've looked at handler but they don't need right as i need to execute a series of tasks in sequence updating the view each time.
Using a Handler, which is a good idea if you are executing from a UI thread...
final Handler h = new Handler();
final Runnable r2 = new Runnable() {
#Override
public void run() {
// do second thing
}
};
Runnable r1 = new Runnable() {
#Override
public void run() {
// do first thing
h.postDelayed(r2, 10000); // 10 second delay
}
};
h.postDelayed(r1, 5000); // 5 second delay
Just to add a sample :
The following code can be executed outside of the UI thread.
Definitely, Handler must be use to delay task in Android
Handler handler = new Handler(Looper.getMainLooper());
final Runnable r = new Runnable() {
public void run() {
//do your stuff here after DELAY milliseconds
}
};
handler.postDelayed(r, DELAY);