Android学习笔记之消息机制
Android的消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程。
1.为什么要使用Handler?
Android规定访问UI只能在主线程中进行,如果在子线程中访问UI,则会抛出异常。同时Android建议不能在主线程中进行耗时的操作,不然会导致程序无法响应即ANR。因此耗时的工作只能交给子线程去做,而子线程却不能直接访问UI,为了解决这个矛盾,Android提供了Handler。Handler的主要作用是将某个任务切换到某个指定的线程中去执行。例如,我们在主线程中创建Handler,在子线程执行完耗时任务后,就可以通过Handler将更新UI的操作切换到主线程中去执行。
2.为什么系统不允许在子线程中访问UI?
因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态。
3.Handler与MessageQueue,Looper
Android的消息机制主要是指Handler的运行机制,Handler的运行需要消息队列(MessageQueue)和消息循环(Looper)的支撑。
消息队列的内部存储结构并不是真正的队列,而是单链表。消息队列只是一个消息的存储单元,不能处理消息,而Looper就是来处理消息的。Looper会无限循环的去查看是否有消息,如果有,就处理,否则一直等待。
Handler创建时会采用当前线程的Looper来构造消息循环系统,如果当前线程没有Looper,则会报错(有的时候,也可以通过构造函数指定一个Looper)。这个当前线程的Looper是通过ThreadLocal来获取的。ThreadLocal并不是线程,它是线程内部的一个数据存储类,通过它可以在指定线性中存储数据和获取数据。
4.MessageQueue工作原理
MessageQueue主要包含两个操作:插入和读取,分别对应enqueueMessage和next两个方法。enQueueMessage是往消息队列中插入一条消息,而next是从消息队列中取出一条消息并将其从消息队列中删除。前面说过,消息队列的内部实现是iyge单链表,它在插入和删除上比较有优势。
这里注意,next方法是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞,当有新消息到来时,它会返回这条消息并将其从单链表中删除。
5.Looper的工作原理
(1)Looper会一直不停的从MessageQueue中查看是否有消息,如果有,则会立刻处理,否则就一直阻塞。
为当前信线程创建Looper的方法如下:
new Thead("Thread1"){
@override
public void run()
{
Looper.prepare();
Handler handler=new Handler();
Looper.loop();
}
}
注意,只有调用了Looper的loop方法后,消息循环系统才真正起作用。
loop方法会调用MessageQueue的next方法来获取消息,当没有消息时,next方法会阻塞,导致loop方法也会阻塞。Looper获得消息后,调用Handler对象的dispatchMessage方法,这个dispatchMessage方法是在创建Handler时所使用的Looper中执行的,这样就就将代码逻辑切换到指定的线程中去了。
loop方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回null。当Looper的quit方法被调用时,它会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,其next方法就会返回null。
(2)Looper也可以退出,主要的方法是quit和quitSafely。前者会直接退出Looper,而后者只是设定一个标记,然后把消息队列中的已有消息处理完毕后才安全退出。Looper退出以后,Handler就无法再顺利发送消息了,其send方法会返回false。
(3)在子线程中创建Looper后,当所有事情完成以后应该调用quit方法来终止消息循环,否则这个子线程会一直处于等待状态。
6.Handler的工作原理
Handler的主要工作是发送和接收消息。消息的发送通过post的方法和send的方法实现,post的方法最终是通过send的方法实现的。
Handler发送消息仅仅是向消息队列中插入一条消息,然后MessageQueue的next方法将消息给Looper处理,最终Looper将消息交给Handler处理,即Handler的dispatchMessage方法被调用。
public void dispatchMessage(Message msg){
if(msg.callback!=null)
{
handleCallback(msg);
}
else
{
if(mCallback!=null)
{
if(mCallback.handleMessage(msg))
{
return;
}
}
handleMessage(msg);
}
}
这里msg.callback对象其实就是一个Runnable对象,就是Handler的post方法所传递的Runnable参数。
mCallback对应的类实现的是Callback接口。当我们不想派生Handler的子类并重写其handleMessage方法时,可以通过Callback来实现。
Android学习笔记之消息机制的更多相关文章
- Android学习笔记(广播机制)
1.Android的广播机制介绍 收听收音机也是一种广播,在收音机中有很多个广播电台,每个广播电台播放的内容都不相同.接受广播时广播(发送方)并不在意我们(接收方)接收到广播时如何处理.好比我们收听交 ...
- android学习笔记21——消息提示Toast
消息提示可细分为两种:大量消息提示——当程序有大量图片.信息需要展示时,采用对话框消息提示: 小量消息提示——当程序只有少量信息需要呈现给用户时,采用轻量级的对话框——Toast; Toast ==& ...
- 【转】 Pro Android学习笔记(八八):了解Handler(2):什么是Handler
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 之前我们有一篇很好的博文<Andro ...
- 【转】Pro Android学习笔记(二):开发环境:基础概念、连接真实设备、生命周期
在Android学习笔记(二):安装环境中已经有相应的内容.看看何为新.这是在source网站上的Android架构图,和标准图没有区别,只是这张图颜色好看多了,录之.本笔记主要讲述Android开发 ...
- Android消息传递之Handler消息机制
前言: 无论是现在所做的项目还是以前的项目中,都会遇见线程之间通信.组件之间通信,目前统一采用EventBus来做处理,在总结学习EventBus之前,觉得还是需要学习总结一下最初的实现方式,也算是不 ...
- Android学习笔记之JSON数据解析
转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...
- 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...
- 【转】 Pro Android学习笔记(六九):HTTP服务(3):HTTP POST MultiPart
目录(?)[-] 建立测试环境 开发环境导入第三方JAR HTTP Post Multipart小例子 HTTP POST不仅可以通过键值对传递参数,还可以携带更为复杂的参数,例如文件.HTTP Po ...
- 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
随机推荐
- Ajax调用SpringMVC ModelAndView 无返回情况
在项目中使用Ajax的时候,success中返回的data一直都是null,也没有报错.在确定Ajax语法没有错误,也没有牵扯跨域问题后,用排除法挨着删除代码,发现是因为Spring MVC会自动把方 ...
- 04 Apache Solr: 目录结构
通过前面的介绍,我们已经能够看到管理员界面并对Solr形成了一个感性的认识.本篇将在物理上深入了解Solr的安装目录结构和Solr示例的主目录结构. 安装目录结构 Solr 6.3.0安 ...
- ATL 获取flash信息
// This goes past the ATL includes #import "C:/WINDOWS/system32/Macromed/Flash/Flash9e.ocx" ...
- 关于C#怎么固定窗口大小属性详解
原文地址:http://zhidao.baidu.com/link?url=aDqlJMuABC8IxXz5drmZcPIHHlTKX2mrfIpyRZNFp0IAB6RSxT24B2XXMRCK1e ...
- Maven中配置默认JDK版本
使用Maven构建项目时,默认是使用jdk1.3版本,目前很多使用泛型的项目肯定是无法通过编译,除了修改项目的pom文件外,还可以在Maven的配置文件settings.xml中添加如下配置来解决: ...
- Ado.net中简单的DBHelper类(增删改查)
private static string connString = "server=.;database=hotel;uid=aa;pwd=123";//最好从配置文件中取出 p ...
- java反射案例
Java反射经典实例 2007-08-29 17:55:25 分类: Java Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射.反射机制是如今很多流行框架的实现 ...
- 使用内存虚拟硬盘 提高ArcGIS server并发性能的一种方法
1 问题提出 1.1 概述 提高ArcGIS server并发性能的方法很多,本文讨论在用户硬件足够强大的情况下(主要是内存足够大),使用内存模拟硬盘来提高数据的读取效率,以达到提高ArcGIS se ...
- C#装箱和拆箱
1.装箱是将值类型转换为引用类型(或者转换为此值类型所实现的任何接口类型)的隐式转换,当 CLR 对值类型进行装箱时,会将该值包装到 System.Object 内部,再将后者存储在托管堆上. ; / ...
- 2.Nginx优化
[教程主题]:Nginx优化 [课程录制]: 创E [主要内容] Nginx 优化 nginx介绍 Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为"engine ...