I am using handler.postDelayed method to create some delay for some animation stuff.
With that i am playing some song as well using Mediaplayer. User can exit this action class by clicking next. But on next screen the same song is continuing even though i called stop method in the next button's onclicklistener.
Is it due to the timedelay that is added which gets executed after the next activity is loaded. Any idea?
handler.postDelayed(new Runnable() {
public void run() {
mp = MediaPlayer.create(getApplicationContext(), R.raw.num2);
mp.start();
imageView1.setImageResource(R.drawable.countcat2);
}
}, 2000);
Did you add a Log to see if run() gets called? I would assume that your handler gets unregistered; after all, postDelayed will wait until the looper kicks in again.
I assume your animation is faster than those 2000ms? You wouldn't be able to have your handler called anyway after your activity is gone, it's accessing imageView1 which I presume is destroyed in onDestroy.
You could consider adding a flag that will force the operation to be called immediately in onDestroy, and/or you could use a Timer. In case of the timer, be sure to not use something like imageView1 after it has been destroyed.
Use threads. And then stop it with an interruption:
Public Thread getThread(final Handler handle, int delay)
{
return new Thread()
{
#Override
public void run()
{
try
{
synchronized(this)
{
Thread.sleep(delay);
handle.post(new Runnable()
{
#Override
public void run()
{
"the code to be exec."
}
});
}
}
catch(Exception e)
{
e.printStackTrace();
}
};
};
}
Or you can use use the postDelayed function
Public Thread getThread(final Handler handle, int delay)
{
return new Thread()
{
#Override
public void run()
{
try
{
synchronized(this)
{
handle.postDelayed(new Runnable()
{
#Override
public void run()
{
"the code to be exec."
}
}, delay);
}
}
catch(Exception e)
{
e.printStackTrace();
}
};
};
}
you will find that there's a little difference between this two methods. To interrupt it, do something like this:
Thread t = getThread(handle, delay);
t.start();
if(t != null)
{
if (t.isAlive())
{
t.interrupt();
}
}
Hope I have helped.
Related
I have a textview which i want to change with a thread and do it again and again (Like a digital clock). But i'm having problems with setting time between 2 changes. Here, the code:
display1 = (TextView) findViewById(R.id.textView1);
Thread timer2 = new Thread(){
#Override
public void run() {
synchronized (this){
runOnUiThread(new Runnable() {
#Override
public void run() {
int i = 0;
display1.setText("" + i);
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
display1.setText("" + (i+1));
}
});
}
}
};
timer2.start();
This sleep(2000); function makes textview invisible for the given time but i want it stand still till the next change. How can i do that?
But i'm having problems with setting time between 2 changes
Do NOT do sleep() on your UI thread. If you want to chain some actions with the delay, split your code into two runnables and the first one should set display1 and then post second runnable with the delay using postDelayed()
EDIT
want one of them to increase 3 per sec, and the other 5 per sec until they reach 1000 for instance
You can make your Runnable post itself until some criteria are met (i.e. time, counter value etc). Just at the end your Runnable check your conditions and if not met, call postDelayed(this, delay); and you are good.
You should use a Handler instead and dispatch your changes to the UI thread.
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
#Override
public void run() {
// Code to be run right away
}
});
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
// Code to be run after 2 seconds
}
}, 2000);
Maybe split up what you need to do into separate methods. Here you have a UI method and a sleep method split up. Hope it helps
private void myMethod() {
new Thread() {
#Override
public void run() {
int i = 0;
doWorkOnUI(String.valueOf(i));
pause(2000);
doWorkOnUI(String.valueOf(i++));
}
}.start();
}
private void pause(int pauseTime) {
try {
Thread.sleep(pauseTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doWorkOnUI(final String string) {
runOnUiThread(new Runnable() {
#Override
public void run() {
display1.setText(string);
}
});
}
I'm trying to make a timer that will do a certain thing after a certain amount of time:
int delay = 1000;
int period = 1000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//Does stuff
}
}, delay, period);
However, the app crashes after the wait period. This is Java code, so it might not be entirely compatible with Android (like while loops). Is there something I'm doing wrong?
Something like this should work, create a handler, and wait 1 second :) This is generally the best way of doing it, its the most tidy and also probably the best on memory too as its not really doing too much, plus as it's only doing it once it is the most simple solution.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// do your stuff
}
}, 1000);
If you would like something to run every one second then something like this would be best:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
If you want a GUI thread then something like this should work:
ActivityName.this.runOnUiThread(new Runnable()
{
public void run(){
try {
while(true) {
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
If your app is crashing after the wait period, then your timer task is doing its job and executing your code on schedule. The problem must then be in your code where run() occurs (for example, you may be trying to update UI elements in a background thread).
If you post more code and your logcat, I can probably be more specific about the error you are getting, but your question was in regards to TimerTask.
Timer and also you can run your code on UI thread:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
timerMethod();
}
}, 0, 1000);
}
private void timerMethod(){
// This method is called directly by the timer
// and runs in the same thread as the timer.
// We call the method that will work with the UI
// through the runOnUiThread method.
this.runOnUiThread(timerTick);
}
private Runnable timerTick = new Runnable() {
public void run() {
// This method runs in the same thread as the UI.
// Do something to the UI thread here
}
};
In my onResume() I have something like this:
#Override
protected void onResume() {
super.onResume();
abc();
}
and in abc() I have:
new Thread(new Runnable() {
public void run() {
MainActivity.activity.runOnUiThread(new Runnable() {
public void run() {
//some code
}
});
}
}).start();
//do something
However it seems runOnUiThread calls onResume through the runOnUiThread because I notice //do something is done twice...
I wonder if there is a work around? Basically I need abc() to wait 10 seconds and then display a message in a textfield on the screen.
I need abc() to wait 10 seconds and then display a message in a textfield on the screen.
You can use a Handler. In abc()
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// do something
}
}, 10000);
http://developer.android.com/reference/android/os/Handler.html
public final boolean postDelayed (Runnable r, long delayMillis)
Added in API level 1
Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.
Parameters
r The Runnable that will be executed.
delayMillis The delay (in milliseconds) until the Runnable will be executed.
You can add code below code in abc().
runOnUiThread(new Runnable() {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//do your task
}
});
I am trying to make a clock, using a TextView :)
Someone here told me that I couldn't use normal threads to change the UI, but Handler or AsyncTask. I managed to get it working a few days ago, but was not a consistent thread.
Now what I want is a consistent thread that is always changing the text of my Textview. I tried using this, but didn't work, any help?
private void startClock() {
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
while (true) {
final long millis = System.currentTimeMillis() - MainActivity.startedAt;
clock.setText("" + millis);
runOnUiThread (new Runnable() {
#Override
public void run() {
clock.setText("" + millis);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, 2000);
}
you should get rid of:
while(true) {
....
sleep(1000);
...
}
because this get your thread stuck forever. your program should work like this:
private Handler mHandler = new Handler();
#Override
public void onResume() {
super.onResume();
mHandler.removeCallbacks(mUpdateClockTask);
mHandler.postDelayed(mUpdateCLockTask, 100);
}
#Override
public void onPause() {
super.onPause();
mHandler.removeCallbacks(mUpdateClockTask);
}
private Runnable mUpdateClockTask = new Runnable() {
public void run() {
updateClock();
mHandler.postDelayed(mUpdateClockTask, 2000);
}
};
and inside updateClock() you do all your UI updates.
Look here for an example https://stackoverflow.com/a/11140429/808940
Also note that you have a duplicate line in your code:
clock.setText(""+millis);
It appears both in the runOnUiThread and in the main handler, it should only appear in the runOnUiThread runnable
Is the code below legit for synchronizing myIntArray?
Will it prevent the three bottom methods from changing myIntArray out of order?
I Want things to happen in the order delayedMethod1, delayedMethod2, method3 and not have one of them screwed up by running before the previous one has finished its changes to myIntArray.
Do the bottom 3 method declarations need the synchronized keywords?
Do the bottom 3 methods need to contain synchronized(myIntArray) blocks?
Should my synchronized block be around the Runnable rather than inside it?
Do I neet notify, wait, or join commands?
public class HelpPlease {
public int myIntArray[] = new int[100];
public void chooseSquare() {
...
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
synchronized(myIntArray) {
delayedMethod1();
}
}
};
handler.postDelayed(r, 1000);
...
Handler handler2=new Handler();
final Runnable r2 = new Runnable()
{
public void run()
{
synchronized(myIntArray) {
delayedMethod2();
}
}
};
handler2.postDelayed(r2, 1000);
...
synchronized(myIntArray) {
method3();
}
}
public void delayedMethod1() {
...
change myIntArray;
otherMethodsABC();
{
public void delayedMethod2() {
...
change myIntArray;
otherMethodsDEF();
}
public void method3() {
...
change myIntArray;
otherMethodsGHI();
}
}
More details: Handler/Runnable delays producing events that are out of sync sometimes
EDIT:
Does this make sense? To run a thread a wait for it to finish? Not sure how to add the delay tho, and that was the whole point.
//Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
delayedMethod();
}
};
//handler.postDelayed(r, COMPUTER_MOVE_DELAY);
ExecutorService es = Executors.newFixedThreadPool(1);
final Future f1 = es.submit(r);
try
{
f1.get();
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
catch (ExecutionException e)
{
throw new RuntimeException(e);
}
Don't try doing this with synchronized blocks. It will only guarantee that no two blocks will run simultaneously, not which order they run. You'd be better off writing a "parent" runnable that executes the delayed methods in the order you want. Alternatively, you can have the first method, when it is finished, post a runnable to run the second, etc., chaining them together.
To be more specific, if you want a delay and then for the three methods to run in sequence, I'd code it like this:
public class HelpPlease {
public int myIntArray[] = new int[100];
Handler handler=new Handler();
public void chooseSquare() {
...
final Runnable r = new Runnable()
{
public void run()
{
delayedMethod1();
delayedMethod2();
method3();
}
};
handler.postDelayed(r, 1000);
}
public void delayedMethod1() {
...
change myIntArray;
otherMethodsABC();
}
public void delayedMethod2() {
...
change myIntArray;
otherMethodsDEF();
}
public void method3() {
...
change myIntArray;
otherMethodsGHI();
}
}
No need for synchronization at all. It's important to use a single Handler to guarantee that multiple calls to chooseSquare() will result in serialized execution of the runnables.
EDIT:
Based on your latest comments, here's how I'd proceed. First, have a single Handler object that is accessible by all your action scheduling code. To use your two examples, these could then be implemented as follows:
public void chooseSquare() {
. . .
if (point_scored) {
makeSquaresGlow(list_of_squares);
playSound(sound_to_play);
handler.postDelayed(new Runnable() {
public void run() {
makeSquaresNotGlow(list_of_squares);
}
}, 1000L);
}
if (time_for_attack(purple)) {
handler.postDelayed(new Runnable() {
public void run() {
launchAttack(purple);
}
}, 1000L);
}
}
Assuming that chooseSquare() is called on the event thread, everything (including the delayed method calls) will also run on the same thread, so no synchronization is needed. There may be race conditions (launchAttack and makeSquaresNotGlow will be scheduled at the same time), but handler will execute one at a time. If the sequencing of these delayed actions is vital, you can define a "meta" action Runnable that accepts a sequence of actions and executes them in a prescribed order at a future time.