Using handler.postDelayed with "for" - android

Basically, I am trying to do something more complicated than that, but this is my problem:
When using handler.postDelayed inside a for loop, there's delay only on the first time, and I wait the delay to kick in every time the for loop repeats:
For example, in this case:
for(int z=0; z<4; z++) {
final int finalZ = z;
handler.postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(play.this, "z:" + finalZ, Toast.LENGTH_SHORT).show();
}
}, 5000);
}
I will get:
Waiting 5 seconds.
z:0
z:1
z:2
z:3
What I want to get:
Waiting 5 seconds.
z:0
Waiting 5 seconds.
z:1
Waiting 5 seconds.
z:2
Waiting 5 seconds.
z:3
I was told not to use Thread.sleep() because it can cause various issues (I didn't quite understand them as I am new to android studio). I am using this in a certain activity (not my Main_Activity).
I am basically trying to change an image's color ever 0.5 seconds or so (more complications go into that, but that's the main idea). Will Thread.sleep() be better?
EDIT: Okay, so thanks to #tynn & #pskink I got this to work (see their answers). But now, another problem came up following this.
If, for example, I will run the exact same code after that, they will both run at the same time, and not one after another, how can i make the second "for" start only after the first "for" has ended?

Here another aspect
private int z=0;
Runnable r = new Runnable() {
#Override
public void run() {
Toast.makeText(play.this, "z:" + z, Toast.LENGTH_SHORT).show();
if(z<4){
z++;
handler.postDelayed(r, 5000);
}
}
}
handler.post(r);

The handler runs your code on another thread, independent of your for loop. The delay is relative to the point where you posted the runnable. Not relative to the previous post. Also it doesn't block the for loop at all. That's the purpose of handlers.
You can assume that any post in this scenario happens at the same time, so you could just do handler.postDelayed(runnable, (z + 1) * 5000). Or maybe define the execution time as absolute with handler.postAtTime(runnable, firstRun + z * 5000)
But since you're trying to do something more complicated than that, you should better consider using a Timer or similar. Maybe RxJava.

Your current code works like this:
hey handler, do it after 5s,
oh and do it after 5s too,
and do it after 5s too,
and this plz do after 5s.
Then we wait 5s and handler is doing those actions in one moment.
What you can do is change it to:
hey handler, do it after 5s,
oh and do it after 10s,
and this after 15s
...
Or you can do it like this:
hey handler do it after 5s, where 'it' action is 'hey handler do it after 5s'.
Then handler will wait 5s and call action 'hey handler do it after 5s'. So handler will have to wait again 5s and do some action after that time.
Here is code for my aproach:
final int finalZ = z;
delayedAction(handler, 0, z);
. . .
void delayedAction(final Handler handler, final int i, final int max) {
if(i<max) {
Toast.makeText(play.this, "z:" + finalZ, Toast.LENGTH_SHORT).show();
handler.postDelayed(new Runnable() {
#Override
public void run() {
delayedAction(handler, i+1, max);
}
});
}
}

Related

How do you tell a function to wait a few seconds in Kotlin?

Kotlin in Android Studio here.
I'm trying to get an imageView to fade into the main view, wait a few seconds, then fade out. For the life of me I can't find any documentation on pausing or waiting anywhere. It's driving me nuts.
How do I tell my function to just chill out and wait for 3 seconds, then continue executing the rest of the function's code?
Ideally, I would have it between:
imageView.startAnimation(animIn)
imageView.startAnimation(animOut)
Any help is very appreciated!
Zoo
You can use Handler,
Handler().postDelayed(Runnable {
//anything you want to start after 3s
}, 3000)
Since this is specific to Kotlin and not just Android. Why not use coroutines?
GlobalScope.launch {
imageView.startAnimation(animIn)
delay(3_000L)
imageView.startAnimation(animOut)
}
This is a naive example, launching on the GlobalScope, and some of the overhead of setting up/getting your head around coroutines might mean it doesn't suit your use case. But if you're already using coroutines in your app, or expecting to in the future then this code is quite clear in it's intent.
import the android.os.Handler and try the following:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// yourAnimationMethod();
}
}, 1000); // 1000 milliseconds
If you are looking for a one-liner, you can try:
(new Handler()).postDelayed(this::yourAnimationMethod, 1000); // 1000 milliseconds
you can use :
Timer("SettingUp", false).schedule(timeyouwant_in_milleseconds) {
imageView.startAnimation(animOut)
}
Stopping the main thread for a few seconds is not a good idea.
You can use handler instead.
The code below will create a task which will be executed after a delay. Anything put inside the run() method will be executed after a delay.
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
imageView.startAnimation(animOut)
}
}, 3000);

Pausing with handler and postDelayed in android

I'm very new to android programming so please forgive my noobie-ness. I'm trying to create a very simple activity that will have one TextView in the middle of the Layout and just have it switch to a different text every couple of seconds. For example, the TextView will say "text1", pause for a couple of seconds, then say "text2, and pause again. Eventually, I want to add more texts and have them all cycle one after another. I know this seems like a super simple thing but I'm mainly trying to learn about threads and handlers at this moment. Anyways, I've read up on how we should keep lengthy things off the UI thread to prevent an error so I thought I'd use a handler to simply switch between 2 texts on screen. Unfortunately, I can't get this to work. Here's some code:
public class MainActivity extends Activity {
String[] myarray = {"text1" , "text2"};
int arraylength = myarray.length;
int count;
Handler handler = new Handler();
TextView mytexts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mytexts = (TextView)findViewById(R.id.my_texts);
mytexts.setText(myarray[0]);
Thread t = new Thread( new Runnable(){
public void run() {
for (int count = 0; count < arraylength; count++){
handler.postDelayed(new Runnable(){
public void run() {
mytexts.setText(myarray[1]);
}
}, 7000);
}
}
});
t.start();
}
}
From what I can see in the logcat, the handler seems to run postDelayed one right after another (in my code's case, it does NOT wait 7 seconds with the postDelay to do another postDelayed). Also, I would like to make the 1 in "mytexts.setText(myarray[1]);" be the same as "count" in the for loop so it can be the same as one of the strings in the array but that gives me an error. I've been stuck on this for hours and other examples I've found online seem way too complicated for someone like me who mainly wants to get the basics down before I can tackle other things. Any help at all with any of this would be much appreciated. Thank you.
postDelayed is non blocking, meaning it would add it to a queue of I'll do this later. So what you are probably seeing is all text updates happening together at the 7th second. I say this because you are postDelaying from the onCreate method when in reality you probably want to do it from onResume or even onPostResume.
Also there is no reason to create a thread to add runnables to the post queue. Your code should look more like this:
(Note the time to delay multiplier)
#Override
protected void onResume() {
super.onResume();
for (int count = 0; count < arraylength; count++){
handler.postDelayed(new Runnable(){
#Override
public void run() {
mytexts.setText(myarray[count]);
}
}, 7000 * (count + 1));
}
}
This is because your loop is setting all your handlers to run after 7 seconds not 7 seconds after each other but but after 7 seconds from now. You can either add in the postDelayed method or use the postAtTime method in handler .
Also, you don't need to do this in a thread, you can get rid of that altogether.

How to run some code for 20 seconds in android

I want to run some code for 20 seconds precisely. It is similar to a loop but instead of having a variable I have time (in seconds).
I should have a time condition like this:
do
{ variable++ }
while (sec < 20)
How it is possible to do this in Android??
My application should run this 20 sec code after the user presses a button.
You can use the Handler class in Android on a runnable and then use the postDelayed() method. That way you will be able to update the UI during that 20 seconds on the progress of the thread. A good example of this is hear. Your code might look something like this ...
Handler handler = new Handler();
final Runnable r = new Runnable(){
public void run() {
//Do thing after 20 sec
}
};
handler.postDelayed(r, 20000);

How to set an image with a delay

I have an "Activity" with three images. When one image is clicked, all the images are to switch to another picture. Is there a way to make the switches such that there is a 2 second delay before the images actually change (i.e. a 2 second delay in every 'for loop' below)? I am trying to do this with a timer but it does not actually to the delay when I run my program:
protected void onCreate(Bundle savedInstanceState) {
image1.setOnClickListener(this);
#Override
public void onClick(View arg0)
{
do_switches();
}
private void do_switches()
{
//loop through all images and change them
for(int j=1 ;j<=3; j++)
{
final int curr2=current;
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
switch(curr2){
case 1:
image1.setImageResource(ImageArray[1]);
break;
case 2:
image2.setImageResource(ImageArray[2]);
break;
case 3:
image3.setImageResource(ImageArray[3]);
break;
}
}
});
}
}, 2000);
}
}
I have also tried using just SystemClock.sleep(2000) instead of the timer but I that didnt work either.I also tried setting up a Thread with a try/catch with no luck or maybe I didn't implement it properly. Is there a way to put this delay on every iteration of my for loop?
Thanks
Not one of best option, but still you can try CountDownTimer.
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use handler.postDelayed(Runnable r, long timeInMillis). Make your runnable that changes the pictures and then call postDelayed() and pass in the runnable and 2000 for the time delay.
Edit: Ahh I see what you are trying to do. As far as I know you aren't going to be able to make a for loop pause for 2 seconds each time through. You can get the same effect though if you chain the postDelayed() calls. Just set up the next runnable and call postDelayed() on it inside the first one, and same for the third one from inside the second one. You will end up with the same functionality as a for loop that pauses for 2 seconds each iteration.

Runnable is executing slower than expected

I'm using a runnable in my Android app to update a countdown timer, as shown in the code below. It appears to work but I noticed my timer takes a few seconds longer than expected. For example, if it's supposed to count down 3 minutes, it takes 3 minutes and 5 seconds. I tried using a timer in a service to manage the countdown display in the main activity. The timer/service worked as expected.
Why doesn't runnable/postDelayed() run for the correct amount of time? Is postDelayed() timing reliable? The runnable decrements a variable then uses it to update an EditText with setText(). Does setText() take too long (a small fraction of a second), so the runnable really runs every 1.x seconds?
Handler handler = new Handler();
Runnable r = new Runnable() {
public void run() {
// decrement the time remaining and update the display
handler.postDelayed(this, 1000);
}
};
...
// start the runnable
handler.postDelayed(r, 1000);
Your code is kinda sorta designed to be inaccurate because you are not accounting for the time taken by the guts of the runnable. You might get improved results by doing something like
public void run(){
startTime = System.currentTimeMillis();
// compare expectedTime to startTime and compensate
// <guts of runnable goes here>
// now wrap it up...
delay = 1000 - (System.currentTimeMillis() - startTime);
if (delay < 0)
delay = 0;
expectedTime = System.currentTimeMillies() + delay;
handler.postDelayed(this, delay);
}
What about using CountDownTimer? I used this for same tasks several times and haven’t met this kind of problem.

Categories

Resources