原文地址:http://blog.csdn.net/xiyangyang8/article/details/50754771

Handler类的作用主要有两种:

1.在新启动的线程中发送消息。

2.在主线程(UI线程)中获取,处理消息。

注:主线程已经封装有Loop的消息队列处理机制,无需再创建。

Handler类包括例如以下方法用于消息发送,处理:

1.void handleMessage(Message msg):处理消息的方法。

2.final boolean hasMessages(int what):检查消息队列是否包括what的值。

3.final boolean hasMessages(int what, Object object):检查消息队列是否包括what的值且object为指定对象。

4.Message obtainMessage():获取消息。

5.sendEmptyMessage(int what):发送空消息。

6.final boolean sendemptyMessageDelayed(int what, long delayMillis):指定多少毫秒之后发送空消息。

7.final boolean sendMessage(Message msg):马上发送消息。

8.final boolean sendMessageDelayed(Message msg, long delayMillis):指定多少毫秒之后发送空消息。

 

demo:自己主动播放动画

以下代码实现是创建一个新线程来隔一定时间之后周期性的改动ImageView所显示的图片。实现一个动画效果。

[java] view
plain
 copy

 

  1. public class HandlerActivity extends Activity {  
  2.         //定义周期性显示的图片ID  
  3.         int[] imageIds = new int[]  
  4.         {  
  5.                 R.drawable.1,  
  6.                 R.drawable.2,  
  7.                 R.drawable.3,  
  8.                 R.drawable.4,  
  9.                 R.drawable.5  
  10.         };  
  11.         int currentImageId = 0;  
  12.         @Override  
  13.         public void onCreate(Bundle savedInstanceState)  
  14.         {  
  15.             super.onCreate(savedInstanceState);  
  16.             setContentView(R.layout.main_activity);  
  17.             final ImageView show = (ImageView) findViewById(R.id.main_bt);  
  18.               
  19.             final Handler myhHandler = new Handler()  
  20.             {  
  21.                 @Override  
  22.                 public void handleMessage(Message msg)  
  23.                 {  
  24.                     //假设该消息是本程序所发送的  
  25.                     if (msg.what == 0x12345) {  
  26.                         //动态的改动所显示的图片  
  27.                         show.setImageResource(imageIds[currentImageId++]%imageIds.length);  
  28.                     }  
  29.                 }  
  30.             };  
  31.             //定义一个计时器,让该计时器周期性的运行指定任务  
  32.             new Timer().schedule(new TimerTask() { //TimerTask对象的本质是启动一个新线程  
  33.                   
  34.                 @Override  
  35.                 public void run() {  
  36.                     // TODO Auto-generated method stub  
  37.                     //发送空消息  
  38.                     myhHandler.sendEmptyMessage(0x12345);  
  39.                 }  
  40.             }, 0, 1200);  
  41.         }  
  42.     }  

说明:当Timertask新线程发送消息时。位于主线程的handleMessage(Message msg)方法自己主动被回调。动态的改动ImagView组件的属性。效果:由新线程来周期性的改动ImageView的属性。从而实现动画效果。

 

Handler,Looper。MessageQueue的工作原理:

Looper:每一个线程仅仅有一个Looper,它负责管理MessageQueue,会不断的从MessageQueue中取出消息,并将消息分发给Handler处理。

MessageQueue:由Looper负责管理。

它採用先进先出的方式来管理Message。

Handler:它能把消息发送给Looper管理的MessageQueue。并负责处理Looper分给它的消息。

注:

  • 在主线程中。系统已经初始化了一个Looper对象,因此程序直接创建Handler就可以,然后就可通过Handler来发送消息,处理消息。
  • 在自己启动的子线程。必须自己创建一个Looper对象,并启动它(分别调用prepare()和loop()方法),以下解说这两个方法:
[java] view
plain
 copy

 

  1. public static final void prepare(){  
  2.         if (sThreadLocal.get() != null) {  
  3.             throw new RuntimeException("Only one Looper may be created per thread");  
  4.         }  
  5.         sThreadLocal.set(new Looper());  
  6.     }  

说明:prepare方法保证线程最多仅仅有一个Looper对象。

[java] view
plain
 copy

 

  1. public void loop(){  
  2.         for (; ;) {  
  3.             Message msg = queue.next();//获取消息队列的下一个消息。假设没有消息,将会堵塞  
  4.             if (msg == null) {//假设消息为null,表明消息队列正在退出  
  5.                 return;  
  6.             }  
  7.             Printer logging = me.mLogging;  
  8.             if (logging != null) {  
  9.                 logging.println("");  
  10.             }  
  11.             msg.target.dispatchMessage(msg);  
  12.             if (logging != null) {  
  13.                 logging.println("");  
  14.             }  
  15.             //使用final修饰该标识符。保证在分发消息的过程中线程标识符不会被改动  
  16.             final long newIdent = Binder.clearCallingIdentity();  
  17.             if (iden != newIdent) {  
  18.                 logging.println("");  
  19.             }  
  20.             msg.recycle();  
  21.         }  
  22.     }  

说明:loop()方法使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息相应的Handler进行处理。

在非主线程中使用Handler的过程例如以下:

  • 调用Looper的prepare()方法为当前线程创建Looper对象(创建Looper对象时。它的构造器会自己主动创建与之配套的MessageQueue)。
  • 有了Looper之后,创建Handler子类的实例,重写handleMessage()方法。该方法负责处理来自于其它线程的消息。
  • 调用Looper的loop()方法启动Looper。

Demo:使用新线程计算质数

该实例同意用户输入一个数值上限,当用户单击“计算”button时,该应用会将该上限数值发送到新启动的线程。让该线程来计算该范围内的全部质数(之所以不直接在UI线程中计算该范围的全部质数。是由于UI线程须要响应用户动作,假设在UI线程中运行一个耗时操作,将会导致UI线程被堵塞。引起ANR异常)。

[java] view
plain
 copy

 

  1. /* 
  2.      * 本实例在线程中创建一个Handler对象,然后UI线程的事件处理方法通过Handler向新线程发送消息。 
  3.      */   
  4.     public class CalPrime extends Activity{  
  5.         static final String UPPER_NUM = "upper";  
  6.         EditText etNum;  
  7.         CalThread calThread;  
  8.         class CalThread extends Thread{  
  9.             public Handler mHandler;  
  10.             public void run(){  
  11.                 Looper.prepare();  
  12.                 mHandler = new Handler(){  
  13.                     @Override  
  14.                     public void handleMessage(Message msg){  
  15.                         if (msg.what == 0x123) {  
  16.                             int upper = msg.getData().getInt(UPPER_NUM);  
  17.                             List<Integer> nums = new ArrayList<Integer>();  
  18.                             //计算从2開始,到upper的全部质数  
  19.                             outer:  
  20.                                 for (int i = 2; i <= upper; i++) {  
  21.                                     //用i除以从2開始。到i的平方根的全部数  
  22.                                     for (int j = 2; j <= Math.sqrt(i); j++) {  
  23.                                         //假设能够整除。表明这个数不是质数  
  24.                                         if (i != 2 && i % j == 0) {  
  25.                                             continue outer;  
  26.                                         }  
  27.                                     }  
  28.                                     nums.add(i);  
  29.                                 }  
  30.                             //使用Toast显示统计出来的全部质数  
  31.                             Toast.makeText(CalPrime.this, nums.toString(), Toast.LENGTH_LONG).show();  
  32.                               
  33.                         }  
  34.                     }  
  35.                 };  
  36.                 Looper.loop();  
  37.             }  
  38.         }  
  39.     }  
  40.     @Override  
  41.     public void onCreate(Bundle savedInstanceState){  
  42.         super.onCreate(savedInstanceState);  
  43.         setContentView(R.layout.main_activity);  
  44.         etNum = (EditText)findViewById(R.id.etNum);  
  45.         CalThread calThread = new CalThread();  
  46.         calThread.start();//启动新线程  
  47.     }  
  48.     //为button的点击事件提供事件处理函数  
  49.     public void cal(View source){  
  50.         //创建消息  
  51.         Message msg = new Message();  
  52.         msg.what = 0x123;  
  53.         Bundle bundle = new Bundle();  
  54.         bundle.putInt(UPPER_NUM, Integer.parseInt(etNum.getText().toString()));  
  55.         msg.setData(bundle);  
  56.         //向新线程中的Handler发送消息  
  57.         calThread.mHandler.sendMessage(msg);  
  58.           
  59.     }  

Handler类和Handler,Loop,MessageQueue的工作原理的更多相关文章

  1. Handler消息传递机制——Handler、Loop、MessageQueue的工作原理

    为了更好地理解Handler的工作原理,先介绍一下与Handler一起工作的几个组件. Message:Handler接收和处理的消息对象. Looper:每个线程只能拥有一个Looper.它的loo ...

  2. 【原创】源码角度分析Android的消息机制系列(四)——MessageQueue的工作原理

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. MessageQueue,主要包含2个操作:插入和读取.读取操作会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage和ne ...

  3. JavaWeb从0开始学(一)-----搭建第一个Web应用程序与JSP工作原理

    以往学习的时候大多是看完书或者看完视频,动手实践一下就OK了.然而过了一段时间我发现东西都忘差不多了,需要复习才能重新掌握.现在开始学习JavaWeb了,我将在这里记录自己的学习的一点一滴,不仅便于自 ...

  4. 详解JVM工作原理和特点

    在我们运行和调试Java程序的时候,经常会提到一个JVM的概念.本文将为大家讲解JVM工作原理和特点,希望对大家有所帮助. AD:网+线下沙龙 | 移动APP模式创新:给你一个做APP的理由>& ...

  5. Salesforce学习之路(十)Aura组件工作原理

    很喜欢曾经看到的一句话:以输出倒逼输入.以输出的形式强制自己学习,确实是高效的学习方式,真的很棒.以下仅为个人学习理解,如有错误,欢迎指出,共同学习. 1. 什么是Lightning Componen ...

  6. android学习11——Handler,Looper,MessageQueue工作原理

    Message是Handler接收和处理的消息对象. 每个线程只能拥有一个Looper.它的loop方法读取MessageQueue中的消息,读到消息之后就把消息交给发送该消息的Handler进行处理 ...

  7. Handler,MessageQueue Loop 和Message的原理解析

    先介绍和handler一起工作的几个组件 Handler的方法介绍 代码示例 package liu.peng.weather; import java.util.Timer; import java ...

  8. Android的消息循环机制 Looper Handler类分析

    Android的消息循环机制 Looper Handler类分析 Looper类说明   Looper 类用来为一个线程跑一个消息循环. 线程在默认情况下是没有消息循环与之关联的,Thread类在ru ...

  9. 面试:Handler 的工作原理是怎样的?

    面试场景 平时开发用到其他线程吗?都是如何处理的? 基本都用 RxJava 的线程调度切换,嗯对,就是那个 observeOn 和 subscribeOn 可以直接处理,比如网络操作,RxJava 提 ...

随机推荐

  1. jsp动态网页开发基础

    JSP基础语法 jsp页面元素构成 jsp页面组成部分有:指令,注释,静态内容,表达式,小脚本,声明. 1.表达式<%=     %> 2.小脚本<%       %> 3.声 ...

  2. TCP协议滑动窗口(一)——控制大批量数据传输速率

    窗口大小:TCP头中一个16位的域,表示当前可用接受缓冲区大小.在每个TCP对等段连接初始化时,告诉对方自己的窗口大小(不一定是满额,假如满额65201字节,可能暂时通告5840字节).若客户端接受数 ...

  3. Android项目实战_手机安全卫士系统加速

    ## 1.本地数据库自动更新的工作机制1. 开启一个服务,定时访问服务器2. 进行版本对比,如果最新版本比较高,获取需要更新的内容3. 将新内容插入到本地数据库中 ## 2.如何处理横竖屏切换1. 指 ...

  4. html5——网络状态

    我们可以通过window.onLine来检测,用户当前的网络状况,返回一个布尔值 window.addEventListener("online",function(){ aler ...

  5. JS——this与new

    this: 1.this只出现在函数中 2.谁调用函数,this就指的是谁 3.new People的this指的就是被创建的对象实例 new: 1.开辟内存空间,存储新创建的对象 2.把this设置 ...

  6. R语言开发环境的搭建

    1.R语言的下载 https://mirrors.tuna.tsinghua.edu.cn/CRAN/ 2.R语言的安装 安装完后,打开R Console 输入 pie(c(0.9, 0.2, 0.3 ...

  7. java 操作clob

    之前在学校的时候做的都是练习,小儿科,遇到的情况完全都在自己的设想范围内.最近老是遇到字段溢出的情况,但是varchar2好像最长也只有4000个字符.所以不得不另辟蹊径,就找上了clob字段. pa ...

  8. Git 学习笔记(W,I,P)

    /*********************** 个人知识水平有限 有任何错误请尽情指出!!谢谢啦 我的Github 求粉 ミ ゚Д゚彡 ***********************/ 参考教程:廖 ...

  9. centOS7卸载google-chrome

    参考: https://www.jianshu.com/p/39d0b8f578d9

  10. php第十二节课

    练习 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...