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);
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'm trying to run a piece of code periodically every 3 seconds that can change the color of a button.
So far I have:
ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(2);
// This schedule a runnable task every 2 minutes
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
queryFeedback2(); // display the data
}
}, 0, 3, TimeUnit.SECONDS);
This code will run the piece of code but will not update my UI with the results.
Firstly, what code be cause my UI updating issues?
And secondly, is this the way I should be running my code periodically? Is there a better way?
Yes, there are few options available.
Thread
Runnable
TimerTask
As stated by alex2k8 in their answer here:
final Runnable r = new Runnable()
{
public void run()
{
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
Or we can use normal thread for example (with original Runner):
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
You may consider your runnable object just as a command that can be
sent to the message queue for execution, and handler as just a helper
object used to send that command.
More details are here
http://developer.android.com/reference/android/os/Handler.html
You can update the UI from
handler. Tutorial for using handler, thread is available here.
Selecting between above mentioned option is really based on what kind of functionality you need. If you only need to do something at few interval then any of the above should be fine.
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.
I am using the following code to access a url:
final Handler handler = new Handler();
Runnable runnable = new Runnable()
{
public void run()
{
img.setImageBitmap(returnBitmap("fromurl"));
handler.postDelayed(this, 50);
}
};
handler.postDelayed(runnable, 2000);
I observed that if the server is not up the app takes ages to close correctly if I hit the back button. Is there anyway way I could speed up the exit procedure.
Runnables will exit automatically when finished with their run() method. If you are employing a loop to do some work, the solution that Jay Ho suggested will help exit from the loop cleanly. If you want to prevent the Handler from executing the runnable (before it posts) you can use handler.removeCallbacksAndMessages(null)1 to clear the queue. Placing it in onDestroy() is your best bet. Otherwise, you're on your own. Once you've spawned a thread, you're at the mercy of the Android operating system to terminate it once its done.
Side note: I've run into problems like this before, and it's usually a call to a system service or the implementation of a Broadcast Listener or Alarm that mucks up the exit process.
private Runnable runnable = new Runnable() {
private boolean killMe=false;
public void run() {
//some work
if(!killMe) {
img.setImageBitmap(returnBitmap("fromurl"));
handler.postDelayed(this, 50);
}
}
public void kill(){
killMe=true;
}
};
ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor();
Runnable longRunningTask = new Runnable();
// submit task to threadpool:
Future longRunningTaskFurure = threadPoolExecutor.submit(longRunningTask);
... ...
// At some point in the future, if you want to kill the task:
longRunningTaskFuture.cancel(true);
... ...
On button click I want to begin a timer of 5 minutes and then execute a method that will check for certain conditions and set off alerts if conditions are right. I've seen examples with timers and postDelay, but don't really understand why one would use one vs another. What is the best way to accomplish what I am trying to do? I don't want to lock up the UI during the 5 minutes. The user should be free to use the app as normal during the countdown.
EDIT: I am trying the postDelayed suggestion but visual studio is not liking something about my code. It looks exactly like examples I've found. My be a mono for android thing.
Handler h = new Handler();
Runnable r = new Runnable(){
public void run()
{
Dialog d = inst2.showBuilder(this, "test", "test");
d.Show();
}
};
h.postDelayed(r, 5000);
Specifically the code block inside of run throws all kinds of "} expected" and "a namespace cannot directly contain members such as fields or methods" exceptions.
Try using Timer Object :
Timer mTimer = new Timer();
mTimer.schedule(new TimerTask()
{
#Override
public void run()
{
// Your code goes here
}
}, 1000); // 1sec
final Handler handler = new Handler();
Timer timer = new Timer();
timer.schedule(new TimerTask()
{
#Override
public void run()
{
handler.post(new Runnable()
{
public void run()
{
// YOUR Code
}
});
}
}, 1000); // 1sec
You can start a simple Thread that will sleep in background for 5 minutes and then call a function. While the thread sleeps in background the UI will not freeze. When the thread finish executing what you want you can set off alerts by sending some intents as notifications and receive them in some Broadcast Receivers.
Hope this helps
Use Handler.postDelayed(Runnable block); method to execute delay, as android also not recommend to use timer.
Handler h = new Handler();
Action myAction = () =>
{
// your code that you want to delay here
};
h.PostDelayed(myAction, 1000);