Amit Prajapati Amit Prajapati - 6 months ago 112
Java Question

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

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?

Answer

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.

Comments