How to stop Runnable in Android that's looping using postDelayed()?

11,872

Solution 1

You might try removing the callback.

imgview.removeCallbacks(r);

In order for this to work, though. you'd have to ensure that r is the same Runnable as the one you posted. You could do this by creating it once, possibly in onCreate. Since the Runnable doesn't have any dependency on the ClickListener anyway, this shouldn't be a problem.

You might also need to do some synchronization in order to prevent the case where you're removing a currently running callback, though, now that i think about it. The volatile boolean running idea is probably less complex overall.

Solution 2

You can control your run() method with a boolean flag:

boolean running = true;
 ...

r = new Runnable()
{
         public void run() 
         {
             if(running)
             {
                 imgview.setImageResource(imageArray[i]);
                 i++;
                 if (i >= imageArray.length) {
                     i = 0;
                 }
                 imgview.postDelayed(r, 20); 
             }
         };
}

If you set running = false later on, your thread will be idle and that's what you want.

Share:
11,872

Related videos on Youtube

Amit Prajapati
Author by

Amit Prajapati

Senior Software Engineer

Updated on June 12, 2022

Comments

  • Amit Prajapati
    Amit Prajapati almost 2 years

    I need to stop a Runnable from running when an image is clicked in my Android app. I'm running this Runnable repeatedly using ImageView.postDelayed():

    r = new Runnable() {
        public void run() {
            imgview.setImageResource(imageArray[i]);
            i++;
            if (i >= imageArray.length) {
                i = 0;
            }
            imgview.postDelayed(r, 20); // set to go off again in 3 seconds.
            // imgview.setOnClickListener(this);
        }
    
    };
    imgview.postDelayed(r, 20); // set first time for 3 seconds
    

    But under certain conditions I want to stop it from running, after it's already started. Here's the full code for my activity:

        public class MainActivity extends Activity  {
    
            int i = 0;
    
            ImageView imgview, imgview2;
            Handler handler = new Handler();
            Runnable r;
            MediaPlayer mMediaPlayer;
            int[] imageArray = { R.drawable.f1, R.drawable.f2, R.drawable.f3,
                    R.drawable.f4, R.drawable.f5, R.drawable.f6, R.drawable.f7,
                    R.drawable.f8, R.drawable.f9, R.drawable.f10, R.drawable.f11,
                    R.drawable.f12, R.drawable.f13, R.drawable.f14, R.drawable.f15,
                    R.drawable.f16, R.drawable.f17, R.drawable.f18, R.drawable.f19,
                    R.drawable.f20, R.drawable.f21, R.drawable.f22, R.drawable.f23,
                    R.drawable.f24, R.drawable.f25, R.drawable.f26, R.drawable.f27,
                    R.drawable.f28 };
    
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.tapp_activity);
    
                imgview = (ImageView) findViewById(R.id.imageView1);
    
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.water);
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    
    
    
                imgview2 = (ImageView) findViewById(R.id.imageView2);
    
                imgview2.setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
    
    
    
    
                        if(i==0)
                        {
                        mMediaPlayer.setLooping(true);
                        mMediaPlayer.start();
                        i=1;
                        r = new Runnable() {
                            public void run() {
                                imgview.setImageResource(imageArray[i]);
                                i++;
                                if (i >= imageArray.length) {
                                    i = 0;
                                }
                                imgview.postDelayed(r, 20); // set to go off again in 3 seconds.
                                // imgview.setOnClickListener(this);
                            }
    
                        };
                        imgview.postDelayed(r, 20); // set first time for 3 seconds
                        }
                        else
                        {
                        i=0;
    
                        mMediaPlayer.stop();
                        imgview.setBackgroundResource(R.drawable.tapstill);
                        }
    
    
    
                    }
                });
    
    
            }
    
    
            @Override
            protected void onDestroy() {
                // TODO Auto-generated method stub
                super.onDestroy();
                mMediaPlayer.stop();
    
            }
    
    
    
        }
    

    What can I change in my code so that my Runnable stops running in the else condition of my onClick() method?

  • Amit Prajapati
    Amit Prajapati over 11 years
    while loop can't stop dear
  • Juvanis
    Juvanis over 11 years
    @AmitPrajapati no it's if condition. it has been a while that I edited my answer.
  • Amit Prajapati
    Amit Prajapati over 11 years
    where i want to use running false
  • Amit Prajapati
    Amit Prajapati over 11 years
    Can u tell how when i need to restart this Runnable than what i want to do
  • Juvanis
    Juvanis over 11 years
    @AmitPrajapati if you set running = true thread will continue to run.