我们进行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. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. public class HandlerTest extends Activity {
  9. /** Called when the activity is first created. */
  10. private Button startButton;
  11. private Button endButton;
  12. @Override
  13. public void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. //根据id获得控件对象
  17. startButton = (Button)findViewById(R.id.startButton);
  18. endButton = (Button)findViewById(R.id.endButton);
  19. //为控件设置监听器
  20. startButton.setOnClickListener(new StartButtonListener());
  21. endButton.setOnClickListener(new EndButtonListener());
  22. }
  23. class StartButtonListener implements OnClickListener{
  24. public void onClick(View v) {
  25. //调用Handler的post()方法,将要执行的线程对象放到队列当中
  26. handler.post(updateThread);
  27. }
  28. }
  29. class EndButtonListener implements OnClickListener{
  30. public void onClick(View v) {
  31. //调用Handler的removeCallbacks()方法,删除队列当中未执行的线程对象
  32. handler.removeCallbacks(updateThread);
  33. }
  34. }
  35. //创建Handler对象
  36. Handler handler = new Handler();
  37. //新建一个线程对象
  38. Runnable updateThread = new Runnable(){
  39. //将要执行的操作写在线程对象的run方法当中
  40. public void run(){
  41. System.out.println("updateThread");
  42. //调用Handler的postDelayed()方法
  43. //这个方法的作用是:将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象
  44. //第一个参数是Runnable类型:将要执行的线程对象
  45. //第二个参数是long类型:延迟的时间,以毫秒为单位
  46. handler.postDelayed(updateThread, 3000);
  47. }
  48. };
  49. }

示例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. import android.app.Activity;
    3. import android.os.Bundle;
    4. import android.os.Handler;
    5. import android.os.Message;
    6. import android.view.View;
    7. import android.view.View.OnClickListener;
    8. import android.widget.Button;
    9. import android.widget.ProgressBar;
    10. public class ProgressBarHandlerTest extends Activity {
    11. /** Called when the activity is first created. */
    12. private ProgressBar progressBar;
    13. private Button startButton;
    14. @Override
    15. public void onCreate(Bundle savedInstanceState) {
    16. super.onCreate(savedInstanceState);
    17. setContentView(R.layout.main);
    18. progressBar = (ProgressBar)findViewById(R.id.progressbar);
    19. startButton = (Button)findViewById(R.id.startButton);
    20. startButton.setOnClickListener(new ProgressBarOnClickListener());
    21. }
    22. class ProgressBarOnClickListener implements OnClickListener{
    23. public void onClick(View v) {
    24. //设置进度条为可见状态
    25. progressBar.setVisibility(View.VISIBLE);
    26. updateBarHandler.post(updateThread);
    27. }
    28. }
    29. //使用匿名内部类来复写Handler当中的handlerMessage()方法
    30. Handler updateBarHandler = new Handler(){
    31. @Override
    32. public void handleMessage(Message msg) {
    33. progressBar.setProgress(msg.arg1);
    34. updateBarHandler.post(updateThread);    //将要执行的线程放入到队列当中
    35. }
    36. };
    37. //线程类,该类使用匿名内部类的方式进行声明
    38. Runnable updateThread = new Runnable(){
    39. int i = 0;
    40. public void run() {
    41. // TODO Auto-generated method stub
    42. System.out.println("Begin Thread");
    43. i+=10;
    44. //得到一个消息对象,Message类是android系统提供的
    45. Message msg = updateBarHandler.obtainMessage();
    46. //将Message对象的arg1参数的值设置为i
    47. msg.arg1 = i;   //用arg1、arg2这两个成员变量传递消息,优点是系统性能消耗较少
    48. try{
    49. Thread.sleep(1000); //让当前线程休眠1000毫秒
    50. }catch(InterruptedException ex){
    51. ex.printStackTrace();
    52. }
    53. //将Message对象加入到消息队列当中
    54. updateBarHandler.sendMessage(msg);
    55. //如果i的值等于100
    56. if (i == 100){
    57. //将线程对象从队列中移除
    58. updateBarHandler.removeCallbacks(updateThread);
    59. }
    60. }
    61. };
    62. }

详解Android Handler的使用-别说你不懂handler(转)的更多相关文章

  1. 详解Android首选项框架ListPreference

    详解Android首选项框架ListPreference 原文地址 探索首选项框架 在深入探讨Android的首选项框架之前,首先构想一个需要使用首选项的场景,然后分析如何实现这一场景.假设你正在编写 ...

  2. 详解android:scaleType属性

    详解android:scaleType属性 转自:http://blog.csdn.net/encienqi/article/details/7913262    http://juliaailse. ...

  3. adb shell 命令详解,android

    http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...

  4. 详解Android Activity---启动模式

    相关的基本概念: 1.任务栈(Task)   若干个Activity的集合的栈表示一个Task.   栈不仅仅只包含自身程序的Activity,它也可以跨应用包含其他应用的Activity,这样有利于 ...

  5. Android Binder IPC详解-Android学习之旅(96)

    linux内存空间与BInder Driver Android进程和linux进程一样,他们只运行在进程固有的虚拟空间中.一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间 ,用户空间是 ...

  6. 详解Android中的四大组件之一:Activity详解

    activity的生命周期 activity的四种状态 running:正在运行,处于活动状态,用户可以点击屏幕,是将activity处于栈顶的状态. paused:暂停,处于失去焦点的时候,处于pa ...

  7. adb shell 命令详解,android, adb logcat

    http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...

  8. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  9. 详解 Android 通信

    详解 Android 通信 :http://www.androidchina.net/5028.html

  10. 详解Android Activity启动模式

    相关的基本概念: 1.任务栈(Task)   若干个Activity的集合的栈表示一个Task.   栈不仅仅只包含自身程序的Activity,它也可以跨应用包含其他应用的Activity,这样有利于 ...

随机推荐

  1. C缩写

    STL:Standard Template Library,标准模板库

  2. python【第九篇】多线程、多进程

    内容提要 paramiko模块 进程.与线程区别 python GIL全局解释器锁 多线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...

  3. vim操作命令-笔记

    显示行号:在vim命令行模式下输入 :set nu 或 :set number 取消显示行号:在vim命令行模式下输入 :set nonu 或 :set nonumber 查看文件编码格式: :set ...

  4. SQL SERVER CEILING 函数 取整时的坑。。。

    CEILING ---返回大于或等于指定数值表达式的最小整数 当舍去同一个大小的值 但是正负方向不一致时要注意小数位四舍五入的问题   例如: SELECT CEILING($123.45), CEI ...

  5. Python 更改cmd中的字色

    没有gui的python程序是在cmd窗口中运行的,黑色背景,灰色的字,确实很复古,不符合现代人的使用习惯-同事在用我写的小工具时,清一色的字色,看起来会没有重点性,因此我就想通过更改cmd中的字色来 ...

  6. PLSQL Developer如何设置自动打开上次编辑的文件

    作为开发人员经常把sql语句保存到文件中以方便下次继续使用,问题是plsqlDev重启后每次都需要手工打开这个文件,好不方便: 以下设置是plsqlDev启动后自动打开上次编辑的文件. 选择配置> ...

  7. linux中VI编辑器使用个人记录

    VI编辑器有三种编辑模式:命令模式.最后行模式.文本编辑模式 启动VI后进入的第一种模式是”命令模式“.从命令模式可进入最后行模式和编辑模式.而后两种模式之间不能直接切换.必须按ESC键退回到命令模式 ...

  8. Canny边缘检测-Wiki

    Canny edge dector 由 John F. Canny 在1986年提出. Canny 算法的发展 Canny算法的步骤 2.1 降噪 2.2 寻找图像的亮度梯度 2.3 非极大值抑制 2 ...

  9. LINUX单网卡绑定多个IP

    在linux下,我们有时候需要给单网卡设置不同的IP地址,这样就涉及到单网卡绑定多个IP地址的情况.使用本方法可以方便的为单网卡绑定多个IP地址.笔者使用的环境是centos5.6,应该在fedora ...

  10. BZOJ 2330 糖果

    Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的 ...