Android之旅十 多个方式实现计时功能

案例:我们要实现的功能是点击按钮开始计时,从0开始计时到10停止,点击Main线程不会影响计时操作,运行如下Android之旅十 多个方式实现计时功能_第1张图片    Android之旅十 多个方式实现计时功能_第2张图片

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

第一种方式:使用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 *
 */

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

你可能感兴趣的:(Android之旅十 多个方式实现计时功能)