Handler类和Handler,Loop,MessageQueue的工作原理
原文地址: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所显示的图片。实现一个动画效果。
- public class HandlerActivity extends Activity {
- //定义周期性显示的图片ID
- int[] imageIds = new int[]
- {
- R.drawable.1,
- R.drawable.2,
- R.drawable.3,
- R.drawable.4,
- R.drawable.5
- };
- int currentImageId = 0;
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main_activity);
- final ImageView show = (ImageView) findViewById(R.id.main_bt);
- final Handler myhHandler = new Handler()
- {
- @Override
- public void handleMessage(Message msg)
- {
- //假设该消息是本程序所发送的
- if (msg.what == 0x12345) {
- //动态的改动所显示的图片
- show.setImageResource(imageIds[currentImageId++]%imageIds.length);
- }
- }
- };
- //定义一个计时器,让该计时器周期性的运行指定任务
- new Timer().schedule(new TimerTask() { //TimerTask对象的本质是启动一个新线程
- @Override
- public void run() {
- // TODO Auto-generated method stub
- //发送空消息
- myhHandler.sendEmptyMessage(0x12345);
- }
- }, 0, 1200);
- }
- }
说明:当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()方法),以下解说这两个方法:
- public static final void prepare(){
- if (sThreadLocal.get() != null) {
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper());
- }
说明:prepare方法保证线程最多仅仅有一个Looper对象。
- public void loop(){
- for (; ;) {
- Message msg = queue.next();//获取消息队列的下一个消息。假设没有消息,将会堵塞
- if (msg == null) {//假设消息为null,表明消息队列正在退出
- return;
- }
- Printer logging = me.mLogging;
- if (logging != null) {
- logging.println("");
- }
- msg.target.dispatchMessage(msg);
- if (logging != null) {
- logging.println("");
- }
- //使用final修饰该标识符。保证在分发消息的过程中线程标识符不会被改动
- final long newIdent = Binder.clearCallingIdentity();
- if (iden != newIdent) {
- logging.println("");
- }
- msg.recycle();
- }
- }
说明:loop()方法使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息相应的Handler进行处理。
在非主线程中使用Handler的过程例如以下:
- 调用Looper的prepare()方法为当前线程创建Looper对象(创建Looper对象时。它的构造器会自己主动创建与之配套的MessageQueue)。
- 有了Looper之后,创建Handler子类的实例,重写handleMessage()方法。该方法负责处理来自于其它线程的消息。
- 调用Looper的loop()方法启动Looper。
Demo:使用新线程计算质数
该实例同意用户输入一个数值上限,当用户单击“计算”button时,该应用会将该上限数值发送到新启动的线程。让该线程来计算该范围内的全部质数(之所以不直接在UI线程中计算该范围的全部质数。是由于UI线程须要响应用户动作,假设在UI线程中运行一个耗时操作,将会导致UI线程被堵塞。引起ANR异常)。
- /*
- * 本实例在线程中创建一个Handler对象,然后UI线程的事件处理方法通过Handler向新线程发送消息。
- */
- 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();
- mHandler = new Handler(){
- @Override
- public 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();
- }
- }
- }
- @Override
- public void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main_activity);
- etNum = (EditText)findViewById(R.id.etNum);
- CalThread calThread = new CalThread();
- calThread.start();//启动新线程
- }
- //为button的点击事件提供事件处理函数
- 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类和Handler,Loop,MessageQueue的工作原理的更多相关文章
- Handler消息传递机制——Handler、Loop、MessageQueue的工作原理
为了更好地理解Handler的工作原理,先介绍一下与Handler一起工作的几个组件. Message:Handler接收和处理的消息对象. Looper:每个线程只能拥有一个Looper.它的loo ...
- 【原创】源码角度分析Android的消息机制系列(四)——MessageQueue的工作原理
ι 版权声明:本文为博主原创文章,未经博主允许不得转载. MessageQueue,主要包含2个操作:插入和读取.读取操作会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage和ne ...
- JavaWeb从0开始学(一)-----搭建第一个Web应用程序与JSP工作原理
以往学习的时候大多是看完书或者看完视频,动手实践一下就OK了.然而过了一段时间我发现东西都忘差不多了,需要复习才能重新掌握.现在开始学习JavaWeb了,我将在这里记录自己的学习的一点一滴,不仅便于自 ...
- 详解JVM工作原理和特点
在我们运行和调试Java程序的时候,经常会提到一个JVM的概念.本文将为大家讲解JVM工作原理和特点,希望对大家有所帮助. AD:网+线下沙龙 | 移动APP模式创新:给你一个做APP的理由>& ...
- Salesforce学习之路(十)Aura组件工作原理
很喜欢曾经看到的一句话:以输出倒逼输入.以输出的形式强制自己学习,确实是高效的学习方式,真的很棒.以下仅为个人学习理解,如有错误,欢迎指出,共同学习. 1. 什么是Lightning Componen ...
- android学习11——Handler,Looper,MessageQueue工作原理
Message是Handler接收和处理的消息对象. 每个线程只能拥有一个Looper.它的loop方法读取MessageQueue中的消息,读到消息之后就把消息交给发送该消息的Handler进行处理 ...
- Handler,MessageQueue Loop 和Message的原理解析
先介绍和handler一起工作的几个组件 Handler的方法介绍 代码示例 package liu.peng.weather; import java.util.Timer; import java ...
- Android的消息循环机制 Looper Handler类分析
Android的消息循环机制 Looper Handler类分析 Looper类说明 Looper 类用来为一个线程跑一个消息循环. 线程在默认情况下是没有消息循环与之关联的,Thread类在ru ...
- 面试:Handler 的工作原理是怎样的?
面试场景 平时开发用到其他线程吗?都是如何处理的? 基本都用 RxJava 的线程调度切换,嗯对,就是那个 observeOn 和 subscribeOn 可以直接处理,比如网络操作,RxJava 提 ...
随机推荐
- SAS学习笔记之《SAS编程与数据挖掘商业案例》(3)变量操作、观测值操作、SAS数据集管理
SAS学习笔记之<SAS编程与数据挖掘商业案例>(3)变量操作.观测值操作.SAS数据集管理 1. SAS变量操作的常用语句 ASSIGNMENT 创建或修改变量 SUM 累加变量或表达式 ...
- C 语言常用方法技巧
C语言常用方法技巧 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impor ...
- 新人转型学习C#
毕业3年,终于在4个多月前,下定决心辞职了.一直以来都想从事软件开发的工作,也觉得自己更加适合这方面的工作.自己如果这一次还是没能往这方面发展的话,感觉以后也不会有机会了. 于是,想着工作先不找了,买 ...
- [ECharts]"echarts/config" is not exists
今天在给Echarts折线图中的数据点增加点击事件的时候总是出现一个 Uncaught Error: [MODULE_MISS]"echarts/config" is not ex ...
- strcmp 与 _tcscmp
strcmp 用来比较ANSI字符串,而_tcscmp用来比较UNICODE(宽字符)的字符串.ANSI字符串中,1个英文字母为1个字节,1个中文字符为2个字节,遇到0字符表示字符串结束.而在UNIC ...
- 阿里P8架构师详解Java性能调优策略
一.性能测试 Ⅰ.测试方法 微基准性能测试 可以精准定位到某个模块或者某个方法的性能问题,例如对比一个方法使用同步实现和非同步实现的性能差异 宏基准性能测试 宏基准性能测试是一个综合测试,需要考虑到测 ...
- CAD绘制一个对齐标注(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawDimAligned 绘制一个对齐标注.详细说明如下: 参数 说明 DOUBLE dExtLine1PointX 第一条界线开始点X值 DOUBLE ...
- linq排序之 根据文本 A-001-002-003 这种类型进行分割排序 空值放于最后
调用 List<string> data = new List<string>() { "D-001-001-001","A-001-004-00 ...
- list.h在用户态下的应用
一.背景 list.h文件位于linux/include下,内核中链表的操作函数都在其中.它有许多关于链表的操作函数,所以我们可以尝试将list.h拉到用户态中来使用,这样,我们在用户态中若要用到链表 ...
- 在引入的css或者js文件后面加参数的作用
有时候可能会遇到js或者css文件引用后传递参数: css和js带参数(形如.css?v=与.js?v=) <script type=”text/javascript” src=”jb51.js ...
