下面我们来做一个例子。分别用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