案例:我們要實現的功能是點擊按鈕開始計時,從0開始計時到10停止,點擊Main線程不會影響計時操作,運行如下
vcC0yrXP1tXiuPa5psTco6zPwsPmuPq087zSwLS31s/t0rvPwqO6PC9wPgo8cD612tK71ta3vcq9o7rKudPDSGFuZGxlctbQtcRwb3N0RGVsYXllZLe9t6ijujwvcD4KPHByZSBjbGFzcz0=”brush:java;”> /**
* 使用Handler中的postDelayed計時
* @author Administrator
*
*/
class Button1ClickListener implements OnClickListener{
@Override
public void onClick(View v) {
//我們沒有調用countTime的start方法,所以它不能當做線程來處理
handler1.post(countTime);
//我們還可以使用如下代碼來終止計時
//handler.removeCallbacks(countTime);
}
}
Handler handler1=new Handler();
Runnable countTime=new Runnable() {
int count=0;
@Override
public void run() {
if(count”+Thread.currentThread().getId());
count++;
show.setText(“計時開始:”+count);
//1s鐘後再次執行countTime
handler1.postDelayed(countTime, 1000);
}
}
};
第二種方式:使用Handler中的sendMessage方法:
/** * 使用Handler中的sendMessage進行計時 * @author Administrator * */ class Button2ClickListener implements OnClickListener{ @Override public void onClick(View v) { countTimeThread.start(); } } Thread countTimeThread=new Thread(){ int count=0; public void run() { while(count"+Thread.currentThread().getId()); count++; //使用以下幾種方式都可以 Message msg=new Message(); //Message msg=Message.obtain(); //Message msg=handler2.obtainMessage(); msg.what=UPDATE; msg.obj=count; handler2.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } }; }; Handler handler2=new Handler(){ @Override public void handleMessage(Message msg) { //打印出來和MainThread一樣 System.out.println("handler2-->"+Thread.currentThread().getId()); if(msg.what==UPDATE){ show.setText("計時開始:"+msg.obj); } } };
第三種方式:使用Handler中的sendMessageDelayed方法:
/** * 使用Handler中的sendMessageDelayed方法計時 * @author Administrator * */ class Button3ClickListener implements OnClickListener{ @Override public void onClick(View v) { Message msg=handler3.obtainMessage(UPDATE); handler3.sendMessageDelayed(msg, 1000); } } final Handler handler3=new Handler(){ int count=0; public void handleMessage(Message msg) { if(count<=10){ if(msg.what==UPDATE){ show.setText("計時開始:"+count); } Message message=handler3.obtainMessage(UPDATE); handler3.sendMessageDelayed(message, 1000); count++; } }; };
第四中方式:使用AsyncTask
1)創建一個CountTimeAsyncTask繼承自AsyncTask:
package com.xin.test; import android.os.AsyncTask; import android.widget.TextView; public class CountTimeAsyncTask extends AsyncTask{ private TextView textView; public CountTimeAsyncTask(TextView textView){ this.textView=textView; } //該方法在UI線程中執行execute方法時會首次被調用,一般用來完成UI的初始化操作 //該方法運行在UI線程中 @Override protected void onPreExecute() { super.onPreExecute(); } //執行完onPreExecute方法後,會執行下面的這個方法,傳入的邊長參數是在execute方法中傳遞過來的 //註意如果是Void,在execute方法中所帶的參數為null,如果不帶參數會報錯 //該方法不運行在UI線程中 @Override protected String doInBackground(Void... params) { int count=0; while(count"+result); } }
2)在UI線程中實例化CountTimeAsyncTask,並調用其execute方法執行該異步操作:
/** * 使用AsyncTask進行計時 * @author Administrator * */ class Button4ClickListener implements OnClickListener{ @Override public void onClick(View v) { //調用後隻會執行一次 AsyncTask countTimeTask=new CountTimeAsyncTask(show); //因為doInBackground中的參數為Void... params,所以這裡必須傳遞參數,否則會報錯 countTimeTask.execute(null); //打印出和MainThread一樣 System.out.println("asyncTask--->"+Thread.currentThread().getId()); } }
我們在主線程操作按鈕中執行的代碼就是一個吐司操作:
/** * 主線程操作 * @author Administrator * */ class Button5ClickListener implements OnClickListener{ @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "我是主線程", Toast.LENGTH_LONG).show(); } }
計時操作總結:
/**
* 計時操作
* 用第一種方式使用的是Handler中的postDelayed計時,因為裡面設置的參數中Runnable我們並沒有調用其實例化(countTime)的start方法,
* 所以這裡並不是線程,所以能夠進行更新UI主線程操作,此時的Handler與Main處於同一線程中,也就是主線程中,所以能夠更新UI
* 用第二種方式使用的是Handler中的handMessage計時,我們用到瞭線程操作countTimeThread,所以更新線程的操作不能在線程中進行
* 我們應該發送一個消息(sendMessage)交給Handler去處理,此時的Handler線程與Main線程處於同一線程中
* 第三種方式使用Handler中的sendMessageDelayed發送消息,相隔多少時間發送,此時的Handler也是與Main處於同一線程中
* 用第四種方式使用的是繼承AsyncTask類,然後調用其execute方法進行計時操作,裡面的操作和線程狀況可參考前面的實例代碼
* 註意Activity中的單線程模式:所有的UI操作都是非線程安全的,並且我們隻能在主線程(UI)線程中對UI進行更新操作
* @author HarderXin *
*/
初學者,希望大傢一起交流分享經驗!