Android的handler消息机制
Hnadler机制中有这么几部分构成,包括 handler、Message、Looper和MessageQueue。要想在一个线程中使用Handler的话必须要有Looper和MessageQueue 的对象。在主线程中Looper不需要我们去创建 系统会自动帮我们调用prepareMainLooper和Looper.prepare方法,looper.prepare首先会到ThreadLocal这个线程级的单例中判断是否已经有了looper对象,如果有了就抛异常,如果没有就new出一个新的对象,并且通过ThreadLocal保存起来。这样就确保了我们的looper对象和当前线程建立起了一一对应的关系。looper对象new自己的时候调用构造方法会创建一个messageQueue对象,并且通过一个final类型的成员变量把MessageQueue保存起来。这样就确保了一个Looper对应唯一的messageQueue。所以 一个线程最多只能有一个looper, 一个looper对应唯一的MessageQueueu。也就是一个线程有唯一的Looper唯一的messageQueue。MessageQueue在创建的过程中会调用nativeInit方法,创建出一个nativeMessageQueue也就是说在jni层也有一个MessageQueue 创建NativeMessaageQueue的时候还会创建一个C++的Looper java层的MessageQueue和NativeMessageQueue通过一个成员变量mPtr建立起关联 mPtr保存了nativeMessageQueue的指针,我们可以通过这个指针随时访问nativeMessageQueue的首地址。需要注意 如果在主线程中调用Looper.prepareMainLooper或者Looper.prepare() 程序会抛出异常,因为系统已经帮我们创建好了无需我们在创建。
looper和messageQueue创建完成之后需要调用Looper.loop让消息循环起来。Looper.loop中有一个死循环,死循环不会阻塞主线程,而且恰恰是因为有这个死循环是我的主线程的代码不会执行完。handler不断的往消息队列中发消息 looper不断的取消息,如果没有消息就会睡在
Message msg = queue.next方法。实际上就是调用了nativeMessageQueue的方法, 利用到了linuxs的管道机制,取出消息之后就通过handler调用disPatchMessage来分发消息。他有三种情况:
如果msg的callback不为空 消息交给这个callback处理
如果msg的callback为空 判断handler mCallback接口 这个接口中就一个方法handleMessage
如果这个callback不为空交给这个handleMessage处理
如果上面两个都为空才交给handler的handleMessage处理消息
创建handler的时候 先到当前的线程中获取looper,如果当前线程没有looper的话那么会抛异常,如果当前线程已经创建了looper,那么我们把这个looper保存到一个final类型的成员变量中,通过这个Lopper找到对应的messageQueue,通过final成员变量进行保存这个messageQueue。这样就可以确保我们在哪个线程创建的handler,消息就会发送到对应的messageQueue中去。如果想在子线程中使用handler,必须首先调用looper.prepare()方法。
handler发送消息:
sendMessage sendEmptyMessage... 实际上都是调用 sendMessageAtTime这个方法,sendMessageAtTime调用了qnqueueMessage方法,这个党法实际上就是把消息放到消息队列中,
消息如何在消息队列中排序:
实际上Messagequeue通过一个成员变量 mMessage保存了消息队列的第一条消息,消息在消息队列中的排序是根据消息要执行的时间先后顺序进行排序。先执行的消息排在前面的,下一条消息通过message的next属性进行保存。enqueueMessage 就是根据新加入进来的消息 要执行的时间跟已有的消息进行比较找到合适的位置放到消息队列中。如果消息需要立即执行,那么就会执行nativeWake方法,实际上就是向管道中写了一个w 那么messageQueue的next方法就不会阻塞可以取出消息。
消息的创建和回收:
如果使用obtain方法来获取消息,那么就会利用到android的消息池。注意这个消息池是全局的,消息池的大小为50条。消息的回收,在Looper.loop()方法中当Handler处理消息之后会调用message.recycle方法回收消息。把要回收的消息所有的成员变量恢复到刚new出来的状态,然后放到消息池中去。
Android的handler消息机制的更多相关文章
- 【Android】Handler消息机制
Handler消息机制主要涉及Looper.Handler.MessageQueue.Message.其中,Looper主要负责获取消息,Handler负责发送消息及处理消息,MessageQueue ...
- Android消息传递之Handler消息机制
前言: 无论是现在所做的项目还是以前的项目中,都会遇见线程之间通信.组件之间通信,目前统一采用EventBus来做处理,在总结学习EventBus之前,觉得还是需要学习总结一下最初的实现方式,也算是不 ...
- Android Handler消息机制不完全解析
1.Handler的作用 Android开发中,我们经常使用Handler进行页面的更新.例如我们需要在一个下载任务完成后,去更新我们的UI效果,因为AndroidUI操作不是线程安全的,也就意味着我 ...
- Handler消息机制的一些原理(直接用code讲解)——Android开发
package com.example.handlertest; import android.os.Bundle; import android.os.Handler; import android ...
- Android Handler消息机制源码解析
好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...
- Android全面解析之由浅及深Handler消息机制
前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Handler的博客可谓是俯拾皆是,而这也是一个老生常谈的话题,可见的他非常基础,也非常重要.但很多的博客,却很少有从入门开始介绍,这在我一开始学习的时候 ...
- Android Handler 消息机制原理解析
前言 做过 Android 开发的童鞋都知道,不能在非主线程修改 UI 控件,因为 Android 规定只能在主线程中访问 UI ,如果在子线程中访问 UI ,那么程序就会抛出异常 android.v ...
- Handler消息机制与Binder IPC机制完全解析
1.Handler消息机制 序列 文章 0 Android消息机制-Handler(framework篇) 1 Android消息机制-Handler(native篇) 2 Android消息机制-H ...
- 浅析Android中的消息机制(转)
原博客地址:http://blog.csdn.net/liuhe688/article/details/6407225 在分析Android消息机制之前,我们先来看一段代码: public class ...
随机推荐
- vue - 官方 - 上手
Vue和其它框架一样,有用CDN或本地JavaScript框架,国内我推荐 bootstrap cdn. 为什么很多人选择CDN呢? CDN:内容分发网络(不同区域不同服务器,更快),减少本地服务器压 ...
- 说说Android应用的persistent属性(转)
1 启动persistent应用 在Android系统中,有一种永久性应用.它们对应的AndroidManifest.xml文件里,会将persistent属性设为true,比如: <appli ...
- 【Java集合源代码剖析】HashMap源代码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在參加CSDN博文大赛,假设您喜欢我的文章.希望您能帮我投一票.谢 ...
- 轻量级批量Omnitty工具安装和简单使用
一.Omnitty简单介绍 在实际工作需要同时对多台docker进行批量处理,为了节省时间,这个运维轻量级工具解决此问题 二.Omnitty简单按照 下载需要安装包和依赖包: omnitty-0.3. ...
- 关于Address already in use: connect问题分析及解决方案
最近给一个公司做项目的时候,在完成上报的功能 的时候,发现数据量稍微大的时候,会出现这样的问题: 错误描述: com.microsoft.sqlserver.jdbc.SQLServerExcepti ...
- WWDC笔记:2011 Session 125 UITableView Changes, Tips and Tricks
What’s New Automatic Dimensions - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSect ...
- mysql备份及还原
mysql怎样复制数据库?或者说,将数据库拷贝到另外一台机? 按照我的理解,复制数据库,如果是: 1.直接拷贝数据库文件,应该先停数据服务,否则拷不出来.但是,生产机器,哪能说停就停呢? 2.在线拷贝 ...
- grails Domian对象转JSON去class以及自己定义字段的最佳方式
grails:2.4.x IDE:Intellij IDEA 13.x grails的Domain对象之间假设存在环形引用.直接使用as JSON仅仅会输出关联对象的id.而且假设使用deep也会报错 ...
- Linux shell 脚本中变量的数学计算【转】
本文转载自:http://blog.csdn.net/qinghezhen/article/details/9194287 首先从一个例子说起: x=1+1 echo $x 你是不是期待着输出2啊?让 ...
- vb6转vb.net
一直在用vb6写软件,但最近系统要做web版,但之前的业务规则全在代码中写死了,没用使用存贮过程,如果在web端重写规则,则工作量太大,项目时间也不允许,只好把业务规则转到vb.net中.现在的vb. ...