4

I have a series of postDelayed handlers. I'm having trouble to set a mathode that stops the handlers when the user is tapping on the stop button at any time I he wants.

I'll appreciate any help someone able to provide. Thanks

while (!lessonIsRunning) {
        Handler handler0 = new Handler();
        handler0.postDelayed(new Runnable() {
          @Override
          public void run() {
              plate1.setVisibility(ImageView.VISIBLE);
              plate2.setVisibility(ImageView.VISIBLE);
              plate3.setVisibility(ImageView.VISIBLE);
          }
        }, 6000);

        Handler handler1 = new Handler();
        handler1.postDelayed(new Runnable() {
          @Override
          public void run() {
              apples1.setVisibility(ImageView.VISIBLE);
          }
        }, 9000);

        Handler handler2 = new Handler();
        handler2.postDelayed(new Runnable() {
          @Override
          public void run() {
              plus1.setVisibility(TextView.VISIBLE);
          }
        }, 9250);
}
public void stopLesson(View V){

}
RBZ
  • 173
  • 2
  • 9

2 Answers2

12

instead of writing the Runnable task in an anonymous way you must define it with a name, so that later you will have a link to it to remove:

//there is no need for multiple handlers 
//handler must be declared outside all functions, in order for you to use it everywhere. 

Handler handler = new Handler(); 
Runnable myFirstTask  = new Runnable (){
         @Override
              public void run() {
                  plate1.setVisibility(ImageView.VISIBLE);
                  plate2.setVisibility(ImageView.VISIBLE);
                  plate3.setVisibility(ImageView.VISIBLE);
              } };

    Runnable mySecondTask = new Runnable(){
        @Override
              public void run() {
                  plus1.setVisibility(TextView.VISIBLE);
              }

    };

    Runnable myThirdTask = new Runnable(){
        @Override
              public void run() {
                  apples1.setVisibility(ImageView.VISIBLE);
              } }

    //you can put different tasks on the same handler object

    while (!lessonIsRunning) {   
            handler.postDelayed(myFirstTask,6000);   
            handler.postDelayed(mySecondTask,9250);   
            handler.postDelayed(myThirdTask,9000); 
} 
public void stopLesson(View V){ 
    //notice that you don't need these, because the handlers are not recursive 
    //you don't have lines "handler.postDelayed(sameTask,someTime);" 
    //in your run Method of the runnable
 if(handler!=null){
    handler.removeCallbacks(myFirstTask);
    handler.removeCallbacks(mySecondTask); 
    handler.removeCallbacks(myThirdTask); 
    //if this method is inside onPause or onDestroy add this line as well: 
    handler=null; 

}
 }
Lena Bru
  • 13,521
  • 11
  • 61
  • 126
4

you can give

handler0.removeCallbacksAndMessages(null);
handler1.removeCallbacksAndMessages(null);
handler2.removeCallbacksAndMessages(null);

a try. The doc says when you submit a null token all callbacks and message are removed.

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • Thanks for the quick answer! the problem is that I get nullPointerException on handler1.removeCallbacksAndMessages(null); when I stop it while handler0 is playing. is there a method that checks the status of a handler? or any boolean condition that you can think about? – RBZ Mar 05 '13 at 16:46
  • the problem is not relate to the removeCallbacksAndMessages argument. Probably handler1 is null. – Blackbelt Mar 05 '13 at 16:54
  • 1
    @RBZ: Also, only call those methods from the handler's main thread (e.g., the main application thread). – CommonsWare Mar 05 '13 at 17:07
  • 1
    +1, haven't tried this but I always prefer passing object rather than null – Inder Kumar Rathore Jun 28 '14 at 06:53