Run Handler Task in Android successively - java

atm i have a problem with my actual Android application.
For explanation:
At first i want to show a Text in a TextView Char by Char. This is my actual Code for this
tvIntro.setText("");
final Handler textHandler = new Handler();
for(int i=0; i<intro.length();i++){
final int finalCount = i;
textHandler.postDelayed(new Runnable() {
#Override
public void run() {
tvIntro.setText(tvIntro.getText() + (intro.charAt(finalCount)+""));
}
}, 150 * i);
}
After the whole text is displayed, i want to play a sound and continuously change the Color of the Screen for 5 Seconds. For this, my code is:
myBackground.setBackgroundColor(Color.RED);// set initial colour
final Thread blink = new Thread(new Runnable() {
public void run() {
while (getRunning()) {
try {
Thread.sleep(100);
if(start[0] !=1){
mp.start();
start[0] = 1;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
updateColor(myBackground);
whichColor = !whichColor;
}
}
});
private void updateColor(final RelativeLayout myBackground) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (whichColor)
myBackground.setBackgroundColor(Color.RED);
else
myBackground.setBackgroundColor(Color.GREEN);
}
});
}
All the functions are working, but i want too finish the first handler, before the second handler is executed. Furthermore the Second handler should stop after x seconds.
I have some problems understanding how the handler and the Threads work.
Would be nice if someone of you have a solution for me.

To delay the performing of tasks until a specified thread (or threads) finishes, add this line immediately after the thread you wish to wait on:
myThread.join();
And then immediately follow it with the code you wish to run after it finishes.
For your second problem, you can set a variable to be the value (in milliseconds) for the amount of time you want to wait before ending the thread, and then decrease that value by 100 (or whatever amount you choose to tell it to sleep for) each time the code runs. Have a check for the value to be less than or equal to zero, and then if that condition returns true, end the thread with an interrupt. So basically:
long timeToRun = 5000, sleepTime = 100;
// Your code here...
Thread.sleep(sleepTime);
timeToRun -= sleepTime;
if(timeToRun <= 0) {
myThread.interrupt();
}
There are likely more graceful ways to accomplish this, but at the very least this should solve your problems.

Related

How to wait for changing different imageviews in android?

I'm using this code to change between different images, but the only image that is visualized is the last one. The TextView "vista_aterrizaje" does not show the expected value in each loop.
I have tried to use invalidate() method before the sleep() one, to try to visualize it in each different loop of the for. But it does not work.
establecerImagen() method is used for changing the imageView.
for (int i = 0; i < 15; i++) {
cur_aterrizaje = aterrizajes[rand.nextInt(aterrizajes.length)];
vista_aterrizaje.setText(cur_aterrizaje);
establecerImagen(cur_aterrizaje);
vista_aterrizaje.();
mapa.invalidate();
try{
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
}
I think that the problem is in the sleep() method but I don't know how to wait a few seconds after every change of the views in order to visualize every change.
Try using CountDownTimer.
// here interval 1000 stands for 1sec,
//so onTick() will be called 15 times, each call after 1 sec interval. so you can set your own values as per your need.
int i=0;
long interval = 1000;
new CountDownTimer((15 * interval), interval){
#Override
public void onTick(long l) {
vista_aterrizaje.setText(i+"");
establecerImagen(cur_aterrizaje);
i++;
}
#Override
public void onFinish() {
}
}.start();
The parameter to sleep() is in milliseconds. So if you want to show each image for 1 second, the parameter should be 1000.
A better way to do it would be like this:
handler=new Handler();
Runnable r=new Runnable() {
public void run() {
//display your image here -- it will be displayed after a 1-second delay
}
};
handler.postDelayed(r, 1000);

Trying To Delay In Java Multiple Times

Need To Do One Animation, Sleep 1000 Then Do The Next Sleep 1000 And So On, Instead It Sleeps For The Entire Time Then Plays All Animations At Once. No Idea What Im Doing.
Tried Timers, Running The Animation Before The tread.sleep And Using A While Loop Instead Of A For.
private void playLaunchAnimation()
{
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
buttons.get(i).startAnimation(animation);
} catch (Exception e){
/*
main declares that it throws InterruptedException. This is an exception that sleep throws when another thread interrupts the current thread while sleep is active. Since this application has not defined another thread to cause the interrupt, it doesn't bother to catch InterruptedException.
*/
}
}
}
Hi, Make sure this code helps you
public static void main(String[] args) throws Exception {
for(int i=0; i < 10;i++) {
try {
Thread.sleep(1000);
System.out.println(i);
if(i==9) {
i=0;
}
} catch (Exception e){
System.out.println("error");
}
}
}
(Answer assumes Android which wasn't entirely clear in OP.)
This is somewhat of a lazy way to do it - but maybe get you thinking. It would
be more interesting to have the handler invoke the next handler so only one handler is declared - but that would be a little more work.
private void playLaunchAnimation() {
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
// Create a handler on the UI thread to execute after a delay.
// The delay is a function of loop index.
//
// It may be necessary to declare buttons final - but your
// OP did not list where it is defined.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
buttons.get(i).startAnimation(animation);
}
}, ((i+1)*1000));
}
}
References:
How to call a method after a delay in Android
Android basics: running code in the UI thread
It sounds like you are calling Thread.Sleep from the User Interface thread. This will ultimately result in the entire User Interface freezing up for the duration of the sleep. What you really want is to launch sleep from a background thread.
For example:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
activity.runOnUiThread(new Runnable() {
buttons.get(i).startAnimation(animation);
});
} catch (Exception e){}
}
});
Another way you could do this using post delay:
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
buttons.get(i).startAnimation(animation);
new android.os.Handler().postDelayed(this, 1000);
}
},
1000);

Count integer with Thread in Activity and update Canvas in View

I'm developing my first android game without xml files for layouts in eclipse. This is calling MyGameView.class(extends View) from MyGameActivity.class(extends View implements OnTouchListener)
MyGameView myView;
myView = new MyGameView(this);
myView.setOnTouchListener(this);
setContentView(myView);
Everytime, I touch (MotionEvent.ACTION_DOWN), I update the Canvas in MyGameView.class with the following code. This is the code I use to update MyGameView.class from MyGameActivity.class.
myView.invalidate();
Yes it works!But I got a serious problem now.I need to move Canvas in MyGameView.class by every 0.3 second.I use Thread to update but it forced stop!!!! I tried again and again and again! I failed!
public void runtime() {
i = 0;
Thread timer = new Thread(new Runnable() {
#Override
public void run() {
while (i<1500) {
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
if (right) {
i++;
//This is static int a from MyGameView.
MyGameView.a += 2;
myView.invalidate();
}
else {
i = 1500;
}
}
}
}
});
timer.start();
}
Updating Static int or boolean to MyGameView.class from MyGameActivity.class with myView.invaldate(); is working. But I can't control it with Thread! Is there something wrong with my Thread running code?
It's probably up to Thread because I can move +2 along X-axis to right everytime I press (MotionEvent.ACTION_DOWN).
//I can Move with this code but not with Thread!
case MotionEvent.ACTION_DOWN:
MyGameView.a += 2;
myView.invalidate();
break;
With Thread, it stops! Please give me a solution for this! In other words, I need to count with time without error and update canvas on every count!
Invalidate must be called from the UI thread. Try calling
postInvalidate()
instead.
See this for reference.

How to spawn enemies periodically

I am attempting to create a game where enemies will spawn randomly and move towards a point on the screen. My problem is that the program waits for them to spawn and them starts moving them. I want them to start moving as they spawn and have a short break in between each one.
Here's the two main methods behind making them move:
public void newLevel() {
runOnUiThread(new Runnable(){
public void run() {
int i = 0;
while( i < 10){
addSpeks();
i++;
try {
Thread.sleep(2000);
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}
}
});
}
public void addSpeks() {
Spek newSpek = new Spek(this);
setRandomRegion();
newSpek.setX(spawnX);
newSpek.setY(spawnY);
relativeLayout.addView(newSpek);
spekList.add(newSpek);
newSpek.setOnClickListener(spekListener);
newSpek.animate().x(finalX).y(finalY).setDuration(8000);
}
Spek is a simple class which extends an ImageView and setRandomRegion() selects a random x, y coordinate on the border of the screen. I have a counter in the while loop for simplicity purposes but I would like to eventually move it to a conditional infinite loop where it only stops if you lose the game.
Thanks for any help and let me know if the problem needs more clarification.
You would have to re-run your thread when it finished, in Android it can be done like this:
First, create your Runnable:
private Runnable SpawnEnemies = new Runnable(){
public void run(){
//Your code here...
spawnHandler.postDelayed(2000, this);
}
};
Then, create a handler, which will be the class that runs the thread (or, well, runnable) and start your Runnable like this:
Handler spawnHandler = new Handler();
spawnHandler.post(new SpawnEnemies());
This will run every 2 seconds, you could also add a boolean or something simmilar to stop the loop manually.
your newLevel() method runs completely on the UI Thread, and Thread.sleep(2000); is making wait your UI Thread 2seconds each iteration. To add this sort of delay you can use an Handler:
Declare the Handler as member class
final Handler mHandler = new Handler();
int i = 0;
and change newLevel accordingly:
public void newLevel() {
mHandler.postDelayed(new Runnable(){
public void run() {
if (i > 10) {
mHandler.removeCallbacks(this);
return;
}
addSpeks();
i++;
mHandler.postDelayed(this, 2000);
}
}), 2000);
}
Another optmization would be to declare the Runnable instance as final member, in order to avoid its instationation every time newLevel is called. Check for typo

Try/Catch delaying but blocking out the code before it in android development

I'm attempting to make a basic app and for part of that app I needed a delay after a button is pressed to allow for a text view to show a word for a second, and then change to another word and then have that display for a second and show another word. S0 3 words, 2 delays. i achieve the first delay using postDelayed() which works fine.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
break;
}
}
The app displays "READY" for one second then opens a new thread and then starts the makePattern runnable which is where the problem is.
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
display.setText("IT WORKED");
}
}
};
Here it should be displaying "GO!", pausing the thread for a second and then displaying "IT WORKED". However when I run it on both my phone and the emulator it displays "READY" for 2 seconds and then skips to "IT WORKED" either displaying "GO!" for such a short amount of time that it can't be seen of skipping over it all together. I have already tried moving the setText("GO!") inside of the catch and that didn't work either. Any Help would be much appreciated.
THANK YOU!
You could create a second Runnable and schedule that using postDelayed, like you're doing for the first. In the same place you schedule the first for 1 second later, you could schedule the second to occur 2 seconds later, which would be 1 second after the first. Or, you could schedule it from within the first runnable for 1-second later. See the "OPTION" comments in the code below.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
timer.postDelayed(showItWorked, 2000); // <-- OPTION 1
break;
}
}
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
timer.postDelayed(showItWorked, 1000); // <-- OPTION 2
}
};
showItWorked = new Runnable()
{
#Override
public void run() {
display.setText("IT WORKED");
}
};
And just to clarify what's going wrong in your existing code...
As Mael mentioned in his comment, your use of Thread.sleep is blocking the UI thread. Just because the the code is within a Runnable does not necessarily mean that it's running on another thread. From the Android documentation for Handler.postDelayed (I'm assuming "timer" is a Handler): "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."

Categories