我们进行Android开发时,Handler可以说是使用非常频繁的一个概念,它的用处不言而喻。本文就详细介绍Handler的基本概念和用法。
Handler的基本概念
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
Handler工具类在多线程中有两方面的应用:
1、发送消息,在不同的线程间发送消息,使用的方法为sendXXX();。
android.os.Handler对象通过下面的方法发送消息的:
sendEmptyMessage(int),发送一个空的消息;
sendMessage(Message),发送消息,消息中可以携带参数;
sendMessageAtTime(Message, long),未来某一时间点发送消息;
sendMessageDelayed(Message, long),延时Nms发送消息。
2、计划任务,在未来执行某任务,使用的方法为postXXX();。
android.os.Handler对象通过下面的方法执行计划任务:
post(Runnable),提交计划任务马上执行;
postAtTime(Runnable, long),提交计划任务在未来的时间点执行;
postDelayed(Runnable, long),提交计划任务延时Nms执行。
使用一个例子简单的来介绍一下Handler。
示例1:一个应用程序中有2个按钮(start、end),当点击start按钮时,执行一个线程,这个线程在控制台输出一串字符串,并且每隔3秒再执行一次线程,直到点击end按钮为止,线程停止。
下图为这个应用程序的界面:
下图为执行程序时控制台的输出:
开发步骤:
1、新建一个Android应用程序
2、在布局文件中添加2个Button控件标签,并为其设置属性和值
3、在Activity中,声明控件变量并根据id获得控件对象
4、在Activity中,创建一个Handler对象
5、在Activity中,创建一个Runnable对象
a) 以匿名内部类的方式
b) 将要执行的操作写在Runnable对象中的run()方法中
i. 打印出一句话
ii. 调用Runnable对象的postDelayed()方法
6、在Activity中,编写start按钮需要的监听器,并绑定。
在这个监听器的Onclick()方法中,调用Handler的post()方法,将要执行的线程对象放到队列当中。
7、在Activity中,编写end按钮需要的监听器,并帮定。
在这个监听器的Onclick()方法中,调用Handler的removeCallbacks ()方法,删除队列当中未执行的线程对象。
下面是Activity的代码:
Java代码
1. package android.handler;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Handler;
6. import android.view.View;
7. import android.view.View.OnClickListener;
8. import android.widget.Button;
9.
10. public class HandlerTest extends Activity {
11. /** Called when the activity is first created. */
12. private Button startButton;
13. private Button endButton;
14.
15. @Override
16. public void onCreate(Bundle savedInstanceState) {
17. super.onCreate(savedInstanceState);
18. setContentView(R.layout.main);
19. //根据id获得控件对象
20. startButton = (Button)findViewById(R.id.startButton);
21. endButton = (Button)findViewById(R.id.endButton);
22. //为控件设置监听器
23. new StartButtonListener());
24. new EndButtonListener());
25. }
26.
27. class StartButtonListener implements OnClickListener{
28. public void onClick(View v) {
29. //调用Handler的post()方法,将要执行的线程对象放到队列当中
30. handler.post(updateThread);
31. }
32. }
33.
34. class EndButtonListener implements OnClickListener{
35. public void onClick(View v) {
36. //调用Handler的removeCallbacks()方法,删除队列当中未执行的线程对象
37. handler.removeCallbacks(updateThread);
38. }
39.
40. }
41.
42. //创建Handler对象
43. new Handler();
44. //新建一个线程对象
45. new Runnable(){
46. //将要执行的操作写在线程对象的run方法当中
47. public void run(){
48. "updateThread");
49. //调用Handler的postDelayed()方法
50. //这个方法的作用是:将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象
51. //第一个参数是Runnable类型:将要执行的线程对象
52. //第二个参数是long类型:延迟的时间,以毫秒为单位
53. 3000);
54. }
55. };
56. }
示例2:一个应用程序中有一个进度条和一个按钮,当点击按钮后,每隔一秒钟进度条前进一部分。
开发步骤:
1、新建一个Android应用程序
2、在布局文件中添加一个progressBar和一个Button,并为其设置属性和值
3、在Activity中,声明控件变量并根据id获得控件对象
4、创建线程对象
a)通过匿名内部类的方式
b)在编写完了5、6步之后再来继续编写这个线程对象里的操作
i. 声明一个变量用来设置进度条的进度
ii. 重写线程类的run方法(),里面编写要执行的操作
1)打印一个字符串
2)进度条的值增加
3)得到一个消息对象
4)设置消息对象arg1的值
5)让线程休眠一秒钟
6)将消息对象放入到消息队列中
7)判断,如果进度条的值等于100,则将线程对象从队列中移除。
5、 创建Handler对象
a) 与示例1不同的地方是,这里是通过匿名内部类的方式来声明的,而示例1是直接new出来的对象。
b) 重写Handler对象的handlerMessage(Message msg)方法。
i. 这个方法传入了一个Message对象,即消息对象,首先设置进度条的进度(这个值是Messag对象里面的一个成员变量arg1)。
ii. 将要执行的线程对象放入到队列当中。
6、 编写Button需要的监听器,并绑定
a) 设置进度条为显示状态。
b) 将要执行的线程对象放入到队列当中。
下面是Activity的代码:
Java代码
1. package android.handler;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Handler;
6. import android.os.Message;
7. import android.view.View;
8. import android.view.View.OnClickListener;
9. import android.widget.Button;
10. import android.widget.ProgressBar;
11.
12. public class ProgressBarHandlerTest extends Activity {
13. /** Called when the activity is first created. */
14.
15. private ProgressBar progressBar;
16. private Button startButton;
17.
18. @Override
19. public void onCreate(Bundle savedInstanceState) {
20. super.onCreate(savedInstanceState);
21. setContentView(R.layout.main);
22.
23. progressBar = (ProgressBar)findViewById(R.id.progressbar);
24. startButton = (Button)findViewById(R.id.startButton);
25.
26. new ProgressBarOnClickListener());
27. }
28.
29. class ProgressBarOnClickListener implements OnClickListener{
30. public void onClick(View v) {
31. //设置进度条为可见状态
32. progressBar.setVisibility(View.VISIBLE);
33. updateBarHandler.post(updateThread);
34. }
35. }
36.
37. //使用匿名内部类来复写Handler当中的handlerMessage()方法
38. new Handler(){
39. @Override
40. public void handleMessage(Message msg) {
41. progressBar.setProgress(msg.arg1);
42. //将要执行的线程放入到队列当中
43. }
44. };
45.
46. //线程类,该类使用匿名内部类的方式进行声明
47. new Runnable(){
48. int i = 0;
49. public void run() {
50. // TODO Auto-generated method stub
51. "Begin Thread");
52. 10;
53. //得到一个消息对象,Message类是android系统提供的
54. Message msg = updateBarHandler.obtainMessage();
55. //将Message对象的arg1参数的值设置为i
56. //用arg1、arg2这两个成员变量传递消息,优点是系统性能消耗较少
57. try{
58. 1000); //让当前线程休眠1000毫秒
59. catch(InterruptedException ex){
60. ex.printStackTrace();
61. }
62. //将Message对象加入到消息队列当中
63. updateBarHandler.sendMessage(msg);
64. //如果i的值等于100
65. if (i == 100){
66. //将线程对象从队列中移除
67. updateBarHandler.removeCallbacks(updateThread);
68. }
69. }
70. };
71. }