为什么要用Handler:

出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的原则:只允许UI线程(亦即主线程)修改Activity中的UI组件。
当一个程序第一次启动时,Android会同时启动一条主线程,主线程主要负责处理与UI相关的事件,如用户的按键事件、用户接触屏幕的事件、屏幕绘图事件,并把相关的事件分发到相应的组件进行处理,所以主线程通常又叫做UI线程。

Handler的概念:

1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个

消息队列来处理各种消息。当你创建子线程时,你可以在你的子线程中拿到父线程中
创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了
。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。

Handler类包含如下方法用于发送、处理消息:

♦ void handlerMessage(Message msg):处理消息的方法,该方法通常用于被重写。
   ♦ final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
♦ sendEmptyMessage(int what):发送空消息
♦ final boolean sendMessage(Message msg):立即发送消息,注意这块返回值,如果message成功的被放到message queue里面则返回true,反之,返回false;(个人建议:对于这类问题不必主观去记它,当实际使用时,直接查看源码即可,源码中有详细的注释)

Handler的作用:
(1)在一个线程中发送消息。
(2)在另一个线程中获取、处理消息。
Handler处理的基本原理:

为了让主线程能及时处理子线程发送的消息,显然只能通过回调的方法来实现----开发者只要重写Handler类中的方法,当新启动的线程发送消息时,消息会发送至与之关联的MessageQueue,而Handler会不断的从MessageQuere中获取并处理消息-----这将导致Handler类中处理消息的方法被回调。
在线程中使用Handler的基本步骤如下:
在被调用线程中完成以下内容:
(1)调用 Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
(2)有了Looper之后,创建Handler子类的实例,重写HandlerMessage()方法,该方法负责处理来自其它线程的消息。
(3)调用Looper的loop()方法启动Looper。

注:若被调用线程是主线程类,由于系统自动为主线程创建了Looper的实例,因此第一、三步骤可省略,而只需要做第2步即可。
在调用线程中完成:
(1)创建message,并填充内容。
(2)使用被调用类创建的Handler实例,调用sendMessage(Message msg)方法。

Handler 与线程的关系
Handler 一般运行于主线程内,也可以运行在子线程中,但是一定要创建Looper对象。主线程中Android已经为之创建了Looper对象

使用Handler的两种常见情况:
1、只能在主UI中修改UI。但实际上,有部分UI需要在子线程中控制其修改逻辑,因此子线程需要通过handler通知主线程修改UI。这在游戏开发中尤其常见,比如需要让新启动的线程周期性的改变UI。、

子线程通知主UI线程修改UI组件的例子,新线程周期性的修改ImageView所显示的图片:

这个例子是Handler在主线程中获取,处理消息,在子线程中发送消息

public class HandlerTest extends Activity
{// 定义周期性显示的图片的IDint[] imageIds = new int[]{R.drawable.java,R.drawable.ee,R.drawable.ajax,R.drawable.xml,R.drawable.classic};int currentImageId = 0;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);final ImageView show = (ImageView) findViewById(R.id.show);final Handler myHandler = new Handler()//在主线程中,获取,处理消息,更新UI组件,可以修改UI组件{@Overridepublic void handleMessage(Message msg){// 如果该消息是本程序所发送的if (msg.what == 0x1233){// 动态地修改所显示的图片show.setImageResource(imageIds[currentImageId++% imageIds.length]);}}};// 定义一个计时器,让该计时器周期性地执行指定任务。子线程通知主线程修改UI组件,实现进程间通信new Timer().schedule(new TimerTask(){@Overridepublic void run(){// 发送空消息myHandler.sendEmptyMessage(0x1233);在线程中发送消息}}, 0, 1200);}
}

2、为避免ANR,应该在子线程中执行耗时较长的操作,而此操作完成后,有可能需要通知主线程修改UI

在子线程中执行耗时任务后,通知主线程修改UI组件的例子:使用新进程计算质数,并用Toast显示

这个例子是在主线程中发送消息,在子线程中获取,处理消息

public class CalPrime extends Activity
{static final String UPPER_NUM = "upper";EditText etNum;CalThread calThread;// 定义一个线程类class CalThread extends Thread{public Handler mHandler;public void run(){Looper.prepare();//创建Looper对象,每个线程使用Handler时都要有一个Looper对象mHandler = new Handler()//在子线程中用handler获取,处理消息{// 定义处理消息的方法@Overridepublic void handleMessage(Message msg){if(msg.what == 0x123){int upper = msg.getData().getInt(UPPER_NUM);List<Integer> nums = new ArrayList<Integer>();// 计算从2开始、到upper的所有质数outer:for (int i = 2 ; i <= upper ; i++){// 用i处于从2开始、到i的平方根的所有数for (int j = 2 ; j <= Math.sqrt(i) ; j++){// 如果可以整除,表明这个数不是质数if(i != 2 && i % j == 0){continue outer;}}nums.add(i);}// 使用Toast显示统计出来的所有质数Toast.makeText(CalPrime.this , nums.toString(), Toast.LENGTH_LONG).show();}}};Looper.loop();//启动Looper}}@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);etNum = (EditText)findViewById(R.id.etNum);calThread = new CalThread();// 启动新线程calThread.start();}// 为按钮的点击事件提供事件处理函数public void cal(View source){// 创建消息Message msg = new Message();msg.what = 0x123;Bundle bundle = new Bundle();bundle.putInt(UPPER_NUM ,Integer.parseInt(etNum.getText().toString()));msg.setData(bundle);// 在主线程中向新线程中的Handler发送消息calThread.mHandler.sendMessage(msg);//在主线程中发送消息}
}

Handler消息传递机制(一)相关推荐

  1. 【Android开发】线程与消息处理-Handler消息传递机制之Looper

    在前面已经介绍了在Android中如何创建.开启.休眠和中断线程.不过,此时并没有在新创建的子线程中对UI界面上的内容进行操作,如果应用前面介绍的方法对UI界面进行操作,将抛出异常. 为此,Andro ...

  2. Android Handler消息传递机制

    Android中只允许UI线程(也就是主线程)修改Activity里的UI组件.实际开发中,新启动的线程需要周期性地改变界面组件的属性值就需要借助Handler的消息传递机制. Handler类 Ha ...

  3. android handler 传递对象,Android之Handler消息传递机制详解

    前言 在Android开发中,多线程应用是非常频繁的,其中Handler机制随处可见. 下面就本人对Handle的一些理解与大家一起分享,共同回顾下Handle异步消息传递机制. 1.Handler是 ...

  4. Handler消息传递机制

    Android中的Handler机制 直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWro ...

  5. Android中Handler消息传递机制应用之子线程不允许操作主线程的组件

    场景 进程 一个Android应用就是一个一个进程,每个应用在各自的进程中运行. 线程 比进程更小的独立运行的基本单位,一个进程可以包含多个线程. 要求 一个TextView和一个Button,点击B ...

  6. Handler消息传递机制(二)Handler,Loop,Message,MessageQueue的工作原理

    Loop,Message,MessageQueue概念理解: Message:Handler发送.接收和处理的消息对象 Looper:每个线程只能拥有一个Looper.它的looper()方法负责循环 ...

  7. Android中的消息机制:Handler消息传递机制

    参考<疯狂android讲义>第2版3.5 P214 一.背景 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为 ...

  8. Handler 消息传递机制

    1,Handler 的概念 Handler 是用来干什么的? 1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创 ...

  9. Android开发:图文分析 Handler通信机制 的工作原理

    前言 在Android开发的多线程应用场景中,Handler机制十分常用 下面,将图文详解 Handler机制 的工作原理 目录 1. 定义 一套 Android 消息传递机制 2. 作用 在多线程的 ...

最新文章

  1. 复习es6-let和const
  2. 电子科技大学技术交流报道
  3. Go语言(Golang)约瑟夫游戏(Joseph)
  4. 产品设计丨价格理论与用户体验
  5. 零基础转行web前端,如何高效的去学习web前端?
  6. ucenter词语过滤原理
  7. 计算机上无线网络开关在哪里,笔记本电脑无线网开关在哪_笔记本电脑如何打开无线网-win7之家...
  8. Makefile、.mk、.bp、Blueprint、Soong、kati工具链的关系
  9. spring学习--AOP术语
  10. apache下虚拟域名配置
  11. php 中文转拼音(包括部分生僻字)
  12. Axure原型分类及存在意义
  13. HC05蓝牙点亮LED
  14. 软件可靠性测试意义,软件可靠性测试方法与目的
  15. web.config与mysql的连接 appsettings_Web.config配置文件中定义了如下数据库连接串
  16. u盘删除文件怎么恢复,误删了u盘文件怎么恢复
  17. PCB 多层板为什么都是偶数层?
  18. 视频流中实时人脸检测
  19. IEEE39+比利时20天然气节点+热网6节点的电气热综合能源系统,包含了CHP、EB、燃气轮机等
  20. 苏州文正学院计算机专业,苏州大学文正学院公共计算机课程教学改革方案(试行)...

热门文章

  1. VS2017-VC++中慎用sizeof
  2. minigui显示时遇到的一个问题(暂时记下来)
  3. linux 块设备驱动 (三)块设备驱动开发
  4. Hadoop自动安装脚本
  5. visual studio 2017 和qt 编译 bitcon源代码
  6. java练气期(1)----java高级(JDBC)
  7. OSI七层网络模型TCP&UDP
  8. GetModuleFileName 获取当前进程主模块完整路径
  9. 【Rsyslog】facilty priority
  10. 1.16 项目实例:Java图书信息查询