2012-07-18 142 views
11

請參閱@Yuri從此處發佈的代碼。 How to stop a timer after certain number of times。如果由於某種原因想要停止它,然後重新啓動它。我該怎麼去做呢?暫停計時器,然後繼續計時

private final static int DELAY = 10000; 
    private final Handler handler = new Handler(); 
    private final Timer timer = new Timer(); 
    private final TimerTask task = new TimerTask() { 
     private int counter = 0; 
     public void run() { 
      handler.post(new Runnable() { 
       public void run() { 
        Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show(); 
       } 
      }); 
      if(++counter == 4) { 
       timer.cancel(); 
      } 

    //do some stuff in my app 
    //restart the timer again 

     } 
    }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     timer.schedule(task, DELAY, DELAY); 

    } 

這是我試過的,但它一直在崩潰。

final int DELAY = 10000; 
     Timer timer; 
     MyTask task; 
     startManager Scanner; 
     Handler handler; 



     public class MyTask extends TimerTask { 

      @Override 
      public void run() { 
       handler.post(new Runnable() { 
        public void run() { 
         //do Stuff here 
         } 
     }); 
    } 
     public class startManager { 

      public startManager() { 
       handler = new Handler(); 
       timer = new Timer(); 
      } 

      public void start() { 

       timer.schedule(task, 0, DELAY); 
      } 

      public void cancel() { 

       timer.cancel(); 
       timer.purge(); 

      } 
     } 

    } 

@Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 

Scanner = new startManager(); 
//do some stuff 
if (...) 
Scanner.cancel() 
//restart the timer and its task 
Scanner=new startManager(); 
     } 

回答

24

如果您已經取消了一個計時器,您不能重新啓動它,您將不得不創建一個新的計時器。

看到這個answer,它包含一個視頻和源代碼我是如何做類似的。

基本上有兩種方法:暫停和恢復

在暫停:

public void pause() { 
    this.timer.cancel(); 
} 

在簡歷:

public void resume() { 
    this.timer = new Timer(); 
    this.timer.schedule(aTask, 0, 1000); 
} 

這使得暫停/恢復的感知。

如果你的計時器基於應用程序的你可以考慮使用StatePattern

拳定義抽象狀態的狀態執行不同的操作:

abstract class TaskState { 
    public void run(); 
    public TaskState next(); 
} 

,並根據需要提供儘可能多的國家。關鍵是一個國家會把你引向另一個國家。

class InitialState extends TaskState { 
    public void run() { 
     System.out.println("starting..."); 
    } 
    public TaskState next() { 
     return new FinalState(); 
    } 
} 
class FinalState extends TaskState { 
    public void run() { 
     System.out.println("Finishing..."); 
    } 
    public TaskState next(){ 
     return new InitialState(); 
    } 
} 

然後你改變你的計時器的狀態。

Timer timer = new Timer(); 
TaskState state = new InitialState(); 

timer.schedule(new TimerTask() { 
    public void run() { 
      this.state.run(); 
      if(shouldChangeState()) { 
       this.state = this.state.next(); 
      } 
    } 
}, 0, 1000); 

最後,如果你需要的是執行同樣的事情,但以不同的速度,你可以考慮使用TimingFramework。它有點複雜,但讓我們做一些很酷的動畫,通過允許某些組件的繪製以不同的速率發生(而不是線性)

+0

我試圖取消它,然後創建一個新的計時器,但它仍然導致它崩潰。你能解釋爲什麼我需要處理程序嗎?我可以把它拿出來嗎?其實,我沒有經理就先試了一下。 – jimmyC 2012-07-18 21:43:51

+0

處理程序允許您發送和處理與線程的MessageQueue關聯的消息和可運行對象。每個Handler實例都與單個線程和該線程的消息隊列相關聯。當您創建一個新的處理程序時,它將綁定到正在創建它的線程的線程/消息隊列 - 此後,它將消息和可運行消息傳遞到該消息隊列,並在消息出來時執行它們隊列。 – SALMAN 2012-07-18 21:48:24

+0

我遇到了一個問題,我認爲當舊的計時器沒有完全停止時,它會產生太多的新計時器。例如,我取消了一個計時器,但是如果任務正在運行,它需要等到它結束。然後(在我的代碼中)取消它之後(在較早的定時器實際完成之前),我啓動一個新的startManager並創建一個新的定時器。有沒有一種方法可以確保在舊任務完全停止運行之前計時器不會啓動。 – jimmyC 2012-07-19 16:19:14

1

設想出來,這是因爲我沒有初始化任務startManager()