HandleThread,handler,thread,asynctask一些总结

下面我们来做一个例子。分别用handler加thread实现,handler加handlerThread实现,AsyncTask实现。

主要就是一个按钮,一个进度条,点击后,进度条每一秒更新一次。

1:handler加thread实现。

public class HandlerThread extends Activity{

	MyHandler handler;
	MyThread updateThread;
	ProgressBar pb_test;
	Button btn_test;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		handler=new MyHandler();
		updateThread=new MyThread();
		
		pb_test=(ProgressBar)findViewById(R.id.pg_bar);
		btn_test=(Button)findViewById(R.id.btn_test);
		
		btn_test.setOnClickListener(new MyListener());
		
	}
	class MyListener implements OnClickListener{
		@Override
		public void onClick(View arg0) {
			// TODO Auto-generated method stub
			handler.post(updateThread);//将要执行的线程加入到队列中
			
		}
	}//处理事件响应的类
	
	class MyHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			pb_test.setProgress(msg.arg1);//更改进度条的状态
		}//处理消息队列
	}
	class MyThread implements Runnable{
			int i=0;
			@Override
			public void run() {
				// TODO Auto-generated method stub
				i+=10;
				System.out.println(Thread.currentThread().getName());
				Message msg=handler.obtainMessage();
				msg.arg1=i;
				try{
					Thread.sleep(1000);//1秒钟更新一次
				}catch(Exception e){
					e.printStackTrace();
				}
				handler.sendMessage(msg);//将message添加到消息队列中
				handler.post(updateThread);//将线程再次加入到handler队列中,实现循环。
				if(i==100){
					handler.removeCallbacks(updateThread);//进度条到达100后,将线程移除。
				}
		}
	}
}

 上述代码中的红色语句打印了当前线程的名称,结果出来是:main。一开始觉得很惊讶,因为按照我的理解,应该是新开辟一个线程的,结果却不是。这样的处理在log中也会报出“too many work in main thread”的提示。查了资料后才知道,这种handler加thread的方式不默认不开辟新线程的。按照java的语法知识,线程的执行是调用线程的start()方法,这里只是把用post将线程直接加入handler队列中,直接执行线程的run方法,并没有调用start()。所有在上述打印的结果显示的是:main。这种方法真是无聊,搞半天,本来想的是把那些费时的方法移出主线程,结果还是没达到结果。

2:下面介绍第二种方式:HandlerThread 加handler

public class MainActivity extends Activity {

	Handler handler;
	HandlerThread handlerThread;
	MyThread myThread;
	ProgressBar pg_test;
	Button btn_test;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		pg_test=(ProgressBar)findViewById(R.id.pg_bar);
		btn_test=(Button)findViewById(R.id.btn_test);
		myThread=new MyThread();
		
		handlerThread=new HandlerThread("handleThread");
		handlerThread.start();//这两句是关键代码	
		
		handler=new Handler(handlerThread.getLooper()){//Looper提供了循环从队列中取得消息的功能
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				pg_test.setProgress(msg.arg1);
			}
		};
		
		btn_test.setOnClickListener(new BtnListener());
	}
	class BtnListener implements OnClickListener{

		@Override
		public void onClick(View arg0) {
			// TODO Auto-generated method stub
			handler.post(myThread);
		}
	}//处理事件响应的代码
	class MyThread implements Runnable{
		int i=0;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			i+=10;
			System.out.println("Thread name:"+Thread.currentThread().getName());
			Message msg=handler.obtainMessage();
			msg.arg1=i;
			try{
				Thread.sleep(1000);
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
			msg.sendToTarget();//将消息发送到与之绑定的那个handler中
			handler.post(myThread);
			if(i==100){
				handler.removeCallbacks(myThread);
			}
		}
	}
}

 上述红色的语句都是为了真正实现另起一个线程所不可少的。在这种方式下,蓝色语句打印的结果符合了我们的要求打印的结果:thread name:handleThread.以此证明确实新开了一个线程。这种方式本人还不是很理解,只是找到了一种可行的线程方案。对于android中需要使用异步操作的地方,我一般还是使用第三种方式AsyncTask。

3:使用AsyncTask实现进度条的更新。

AsyncTask是android推荐的进行异步操作的类,使用如下

public class AsyncTaskTest extends Activity{

	ProgressBar pb_test;
	Button btn_test;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		pb_test=(ProgressBar)findViewById(R.id.pg_bar);
		btn_test=(Button)findViewById(R.id.btn_test);

		btn_test.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				try{
					new UpdateProgressAsync().execute("");//启动异步类,执行doInbackground方法
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		});
	}
	class UpdateProgressAsync extends AsyncTask<String,Integer,String>{//这三个参数还可以是object

		@Override
		protected String doInBackground(String... arg0) {
			// TODO Auto-generated method stub
			int i=0;
			while(i<=100){
				i+=10;
				try{
					Thread.sleep(1000);
					publishProgress(i);//调用下面的onProgressUpdate方法更新主线程UI
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			return null;
		}
		@Override
		protected void onPostExecute(String result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);//可以根据doInBackground的返回结果更新主线程UI
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
			pb_test.setProgress(values[0]);//获取publishProgress(i)传过来的i值,使用它更新进度条的值。
		}
	}
}

 使用这种方式将耗时的操作全放在doInbackground中,结果返回,可以通过onPostExecute修改主线程UI。还可以通过onProgressUpdate看进度。完全不会阻塞主线程。参数不仅可以是string类型,还可以是Object。

三个例子所需要的源码可以参考下面链接,运行的时候,需要修改manifest中的程序入口。

http://download.csdn.net/detail/beiweideqidaozhe/7588113

猜你喜欢

转载自zzcjobstudy.iteye.com/blog/2088013