private EditText edit;
private TextView text;
private Button get, start, stop;
private int i = 0;
private Timer timer = null;
private TimerTask task = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView()
{
edit = (EditText)findViewById(R.id.editText1);
text = (TextView)findViewById(R.id.textView1);
get = (Button)findViewById(R.id.button1);
start = (Button)findViewById(R.id.button2);
stop = (Button)findViewById(R.id.button3);
get.setOnClickListener(this);
start.setOnClickListener(this);
stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.button1:
if(timer!=null){
stopTime();
}
text.setText(edit.getText().toString());
if(!TextUtils.isEmpty(edit.getText()))
{
i = Integer.parseInt(edit.getText().toString());
}
break;
case R.id.button2:
startTime();
break;
case R.id.button3:
stopTime();
break;
}
}
private Handler mHandler = new Handler(){
public void handleMessage(Message msg){
text.setText(msg.arg1 + "");
startTime();
};
};
private void startTime() {
// TODO Auto-generated method stub
timer = new Timer();
task = new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
if(TextUtils.isEmpty(text.getText()))
{
return;
}
--i;
Message message = mHandler.obtainMessage();
message.arg1 = i;
mHandler.sendMessage(message);
}
};
timer.schedule(task, 1000);
}
private void stopTime() {
// TODO Auto-generated method stub
timer.cancel();
}
}
關鍵點:
Timer,TimerTask:Java爲我們提供的計時器的工具類,即Timer和TimerTask。 Timer是一個普通的類,其中有幾個重要的方法;而TimerTask則是一個抽象類,其中有一個抽象方法run(),類似線程中的run()方法,我們使用Timer創建一個他的對象,然後使用這對象的schedule方法來完成這種間隔的操作。
schedule方法有三個參數
第一個參數就是TimerTask類型的對象,我們實現TimerTask的run()方法就是要週期執行的一個任務;
第二個參數有兩種類型,第一種是long類型,表示多長時間後開始執行,另一種是Date類型,表示從那個時間後開始執行;
第三個參數就是執行的週期,爲long類型。
schedule方法還有一種兩個參數的執行重載,第一個參數仍然是TimerTask,第二個表示爲long的形式表示多長時間後執行一次,爲Date就表示某個時間後執行一次。
Timer就是一個線程,使用schedule方法完成對TimerTask的調度,多個TimerTask可以共用一個Timer,也就是說Timer對象調用一次schedule方法就是創建了一個線程,並且調用一次schedule後TimerTask是無限制的循環下去的,使用Timer的cancel()停止操作。當然同一個Timer執行一次cancel()方法後,所有Timer線程都被終止。
Handler:我們需要把耗時的操作,放在一個子線程中,因爲子線程涉及到UI更新,但是當子線程中有涉及到操作UI的操作時,就會對主線程產生危險,也就是說,更新UI只能在主線程中更新,在子線程中操作是危險的. 這個時候,Handler就出現了來解決這個複雜的問題,由於Handler運行在主線程中(UI線程中),它與子線程可以通過Message對象來傳遞數據,這個時候,Handler就承擔着接受子線程傳過來的(子線程用sedMessage()方法傳遞)Message對象,(裏面包含數據), 把這些消息放入主線程隊列中,配合主線程進行更新UI。
Message:Message 可以傳遞的參數有:
1. arg1 arg2 整數類型,是setData的低成本替代品。傳遞簡單類型
2. Object 類型 obj
3. what 用戶自定義的消息代碼,這樣接受者可以瞭解這個消息的信息。每個handler各自包含自己的消息代碼,所以不用擔心自定義的消息跟其他handlers有衝突。
4.其他的可以通過Bundle進行傳遞
Message可以通過new Message構造來創建一個新的Message,但是這種方式很不好,不建議使用。最好使用Message.obtain()來獲取Message實例,它創建了消息池來處理的。
所謂的消息機制其實很簡單,實現這種機制需要只需要四步:
1、實例化Looper(因爲實例化Handler時需要一個looper);
2、實例化Handler,這裏需要覆蓋handleMessage方法,處理收到的消息;
3、 實例化Message對象,調用已經實例化好的handler對象的obtainMessage方法,把數據傳給obtainMessage方法,obtainMessage方法就會實例化一個Message對象。(這裏也可以發送實現Runnable接口的對象);
4、調用Handler的sendMessage方法把實例化好的Message對象發送出去,handleMessage方法處理Message對象。
對每個線程過程都是一樣的,只要按照上面的四個步驟來就可以發送和接收消息了。