MainActivity如下:

  1. package cc.c;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.os.Handler;
  6. import android.os.Looper;
  7. import android.os.Message;
  8. import android.widget.TextView;
  9. /**
  10. * Demo描述:
  11. *
  12. * 示例步骤如下:
  13. * 1 子线程给子线程本身发送消息
  14. * 2 收到1的消息后,子线程给主线程发送消息
  15. * 3 收到2的消息后,主线程给子线程发送消息
  16. *
  17. * 为实现子线程给自己本身发送消息,关键还是在于构造Handler时传入的Looper.
  18. * 在此就传入该子线程自己的Looper即调用Looper.myLooper(),代码如下:
  19. * Looper.prepare();
  20. * mHandlerTest1=new HandlerTest1(Looper.myLooper());
  21. * Looper.loop();
  22. *
  23. * 所以当mHandlerTest1.sendMessage(message);发送消息时
  24. * 当然是发送到了它自己的消息队列.
  25. *
  26. * 当子线程中收到自己发送的消息后,可继续发送消息到主线程.此时只要注意构造
  27. * Handler时传入的Handler是主线程的Handler即可,即getMainLooper().
  28. * 其余没啥可说的.
  29. *
  30. *
  31. * 在主线程处理消息后再发消息到子线程
  32. *
  33. *
  34. * 其实这些线程间发送消息,没有什么;关键还是在于构造Handler时传入谁的Looper.
  35. *
  36. */
  37. public class MainActivity extends Activity {
  38. private TextView mTextView;
  39. private HandlerTest1 mHandlerTest1;
  40. private HandlerTest2 mHandlerTest2;
  41. private int counter=0;
  42. @Override
  43. protected void onCreate(Bundle savedInstanceState) {
  44. super.onCreate(savedInstanceState);
  45. setContentView(R.layout.main);
  46. init();
  47. }
  48.  
  49. private void init() {
  50. mTextView = (TextView) findViewById(R.id.textView);
  51.  
  52. //1 子线程发送消息给本身
  53. new Thread() {
  54. public void run() {
  55. Looper.prepare();
  56. mHandlerTest1=new HandlerTest1(Looper.myLooper());
  57. Message message = new Message();
  58. message.obj = "子线程发送的消息Hi~Hi";
  59. mHandlerTest1.sendMessage(message);
  60. Looper.loop();
  61. };
  62. }.start();
  63.  
  64. }
  65.  
  66. private class HandlerTest1 extends Handler {
  67.  
  68. private HandlerTest1(Looper looper) {
  69. super(looper);
  70. }
  71.  
  72. @Override
  73. public void handleMessage(Message msg) {
  74. super.handleMessage(msg);
  75. System.out.println("子线程收到:" + msg.obj);
  76.  
  77. //2 收到消息后可再发消息到主线程
  78. mHandlerTest2=new HandlerTest2(getMainLooper());
  79. Message message = new Message();
  80. message.obj = "O(∩_∩)O";
  81. mHandlerTest2.sendMessage(message);
  82. }
  83. }
  84.  
  85. private class HandlerTest2 extends Handler {
  86.  
  87. private HandlerTest2(Looper looper) {
  88. super(looper);
  89. }
  90.  
  91. @Override
  92. public void handleMessage(Message msg) {
  93. super.handleMessage(msg);
  94. mTextView.setText("在主线程中,收到子线程发来消息:" + msg.obj);
  95.  
  96. //3 收到消息后再发消息到子线程
  97. if (counter==0) {
  98. Message message = new Message();
  99. message.obj = "主线程发送的消息Xi~Xi";
  100. mHandlerTest1.sendMessage(message);
  101. counter++;
  102. }
  103.  
  104. }
  105. }
  106.  
  107. }

main.xml如下:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. >
  6.  
  7. <TextView
  8. android:id="@+id/textView"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="@string/hello_world"
  12. android:layout_centerInParent="true"
  13. android:layout_marginTop="70dip" />
  14.  
  15. </RelativeLayout>

对于Android Handler与Message的多线程消息的处理,为什我以下代码会死掉? 看看,

 

1.线程没有终止条件,会一直给主线程发消息,主线程不停的调用handleMessage代码,很容易ANR(应用程序不响应)
2.handler.obtainMessage()得到message对象比new Message();更高效

Android Handler机制 怎使用?

 

Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用线程也会堵塞。每个Handler对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue)。如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
在主线程中,可以直接使用new Handler()创建Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样创建Handler则会报错,因为Android系统默认情况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。这种情况下,需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上;或者通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。
Handler发送的消息都会加入到Looper的MessageQueue中。一说Handler包含两个队列:线程队列和消息队列;使用Handler.post()可以将线程对象加入到线程队列中;使用Handler.sendMessage()可以将消息对象加入到消息队列中。通过源码分析证实,Handler只有一个消息队列,即MessageQueue。通过post()传进去的线程对象将会被封装成消息对象后传入MessageQueue。
使用post()将线程对象放到消息队列中后,当Looper轮询到该线程执行时,实际上并不会单独开启一个新线程,而仍然在当前Looper绑定的线程中执行,Handler只是调用了该线程对象的run()而已。如,在子线程中定义了更新UI的指令,若直接开启将该线程执行,则会报错;而通过post()将其加入到主线程的Looper中并执行,就可以实现UI的更新。
使用sendMessage()将消息对象加入到消息队列后,当Looper轮询到该消息时,就会调用Handler的handleMessage()来对其进行处理。再以更新UI为例,使用这种方法的话,就先将主线程的Looper绑定在Handler对象上,重载handleMessage()来处理UI更新,然后向其发送消息就可以了。

Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解的更多相关文章

  1. Handler具体解释系列(四)——利用Handler在主线程与子线程之间互发消息

    MainActivity例如以下: package cc.c; import android.app.Activity; import android.os.Bundle; import androi ...

  2. Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

    keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...

  3. Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息

    之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: ...

  4. android handle详解2 主线程给子线程发送消息

    按照android handler详解分析的原理我们可以知道,在主线程中创建handle对象的时候,主线程默认创建了一个loop对象使用threalocal函数将loop对象和主线程绑定. 我们能不能 ...

  5. Handler主线程和子线程相通信

    //创建主线程的handlerprivate Handler handler = new Handler(){ @Override public void handleMessage(Message ...

  6. 19 主线程向子线程发送信息(handler)

    package com.fmy.handler; import android.app.Activity; import android.os.Bundle; import android.os.Ha ...

  7. Handler主线程子线程之间的互相通信

    Handler主线程子线程之间的互相通信 package com.wyl.dansnote; import android.app.Activity; import android.os.Bundle ...

  8. Mybatis源码详解系列(四)--你不知道的Mybatis用法和细节

    简介 这是 Mybatis 系列博客的第四篇,我本来打算详细讲解 mybatis 的配置.映射器.动态 sql 等,但Mybatis官方中文文档对这部分内容的介绍已经足够详细了,有需要的可以直接参考. ...

  9. Eureka详解系列(四)--Eureka Client部分的源码和配置

    简介 按照原定的计划,我将分三个部分来分析 Eureka 的源码: Eureka 的配置体系(已经写完,见Eureka详解系列(三)--探索Eureka强大的配置体系): Eureka Client ...

随机推荐

  1. ie6下兼容问题

    最小高度问题:overflow:hidden 在ie6.7下 li本身不浮动 内容浮动 li产生3像素间隙 解决:vertical-align:top; 二.当ie6下最小高度问题和li间隙问题共存时 ...

  2. 算法心得1:由$nlogn$复杂度的LIS算法引起的思考

    LIS(Longest Increasing Subsequence)是一类典型的动态规划类问题,简化描述如下: 给定$N(n) = \{1,2...,n\}$的一个排列$P(n)$,求$P(n)$中 ...

  3. Borg Maze 分类: POJ 2015-07-27 15:28 5人阅读 评论(0) 收藏

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9971   Accepted: 3347 Description The B ...

  4. C#事物执行数据

    public class sqlservershiwu { public string sqlconString = "Data Source=.;Initial Catalog=TestD ...

  5. 使用Jvisualvm监控JVM的内存、CPU、线程

    最近做性能测试发现很多性能问题,面对一些开发小白的数据结构思想,真想喊一声:放开那个代码,让我来!冲动. 面对WEB站点开发,性能测试是经常要做的,下面一种介绍如何结合性能测试工具,更好的监控WEB服 ...

  6. 对torch的一点感想

    torch是一个基于LuaJIT的科学计算框架,知乎上有个人回答说torch比较适合科研用途, torch与matlab的很多函数很相似

  7. php基础复习(一)smarty模板

    一.基本配置第一步:下载smarty:官网www.smarty.net第二步:加载类文件和更改配置 1. //加载类文件 require_once '../libs/Smarty.class.php' ...

  8. 2016年10月15日 星期六 --出埃及记 Exodus 18:26

    2016年10月15日 星期六 --出埃及记 Exodus 18:26 They served as judges for the people at all times. The difficult ...

  9. linux下svn常用指令

    windows下的TortoiseSVN是资源管理器的一个插件,以覆盖图标表示文件状态,几乎所以命令都有图形界面支持,比较好用,这里就不多说.主要说说linux下svn的使用,因为linux下大部分的 ...

  10. CentOS6 启动流程图文解剖

    我们在使用Linux操作系统的时候,我们只需按下电源键,等待,然后输入账户和密码就可以使用Linux操作系统了.那么在按下电源到输入账号和密码之前,操作系统都做了些什么?下面就来讲述在这段时间发生的动 ...