案例:我们要实现的功能是点击按钮开始计时,从0开始计时到10停止,点击Main线程不会影响计时操作,运行如下   

上面,大家也看到了,我使用了不同的方式来实现这个功能,下面跟大家来分享一下:

第一种方式:使用Handler中的postDelayed方法:

    /**  	 * 使用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<10){  				//打印出来和MainThread一样  				System.out.println("CountTime--->"+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<10){      			try {  					Thread.sleep(1000);  					//打印出来和MainThread不同  					System.out.println("countTimeThread-->"+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<Void, Integer, String>{    	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<10){  			publishProgress(count);//调用该方法一次,下面的onProgressUpdate会被执行一次  			try {  				Thread.sleep(1000);  				count++;  			} catch (InterruptedException e) {  				e.printStackTrace();  			}  		}  		return count+"";  	}    	//执行这个方法,可以用来更新UI中控件的变化,例如进度条信息变化等等  	//该方法运行在UI线程中  	@Override  	protected void onProgressUpdate(Integer... values) {  		int count=values[0];  		System.out.println(3);  		textView.setText("计时开始:"+count);  	}  	  	//doInBackground方法执行完后会执行该方法,可以用来提示用户异步操作结束  	@Override  	protected void onPostExecute(String result) {  		textView.setText("计时结束-->"+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 *
 */

初学者,希望大家一起交流分享经验!