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